]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
gh-100239: specialize long tail of binary operations (#128722)
authorIrit Katriel <1055913+iritkatriel@users.noreply.github.com>
Thu, 16 Jan 2025 15:22:13 +0000 (15:22 +0000)
committerGitHub <noreply@github.com>
Thu, 16 Jan 2025 15:22:13 +0000 (15:22 +0000)
21 files changed:
Include/internal/pycore_code.h
Include/internal/pycore_magic_number.h
Include/internal/pycore_opcode_metadata.h
Include/internal/pycore_uop_ids.h
Include/internal/pycore_uop_metadata.h
Include/opcode_ids.h
Lib/_opcode_metadata.py
Lib/opcode.py
Lib/test/test_code.py
Lib/test/test_dis.py
Lib/test/test_monitoring.py
Lib/test/test_opcache.py
Misc/NEWS.d/next/Core_and_Builtins/2025-01-10-23-54-16.gh-issue-100239.ijOOUs.rst [new file with mode: 0644]
Python/bytecodes.c
Python/executor_cases.c.h
Python/generated_cases.c.h
Python/opcode_targets.h
Python/optimizer_cases.c.h
Python/specialize.c
Tools/c-analyzer/cpython/ignored.tsv
Tools/cases_generator/parsing.py

index d97fe81a2fc54a11f9cd89e43a201d02369f5db1..01d41446fdb0cf2bfe0f253ffd91c3b55040f5ca 100644 (file)
@@ -100,6 +100,7 @@ typedef struct {
 
 typedef struct {
     _Py_BackoffCounter counter;
+    uint16_t external_cache[4];
 } _PyBinaryOpCache;
 
 #define INLINE_CACHE_ENTRIES_BINARY_OP CACHE_ENTRIES(_PyBinaryOpCache)
@@ -438,7 +439,7 @@ write_u64(uint16_t *p, uint64_t val)
 }
 
 static inline void
-write_obj(uint16_t *p, PyObject *val)
+write_ptr(uint16_t *p, void *val)
 {
     memcpy(p, &val, sizeof(val));
 }
@@ -576,6 +577,16 @@ adaptive_counter_backoff(_Py_BackoffCounter counter) {
     return restart_backoff_counter(counter);
 }
 
+/* Specialization Extensions */
+
+/* callbacks for an external specialization */
+typedef int (*binaryopguardfunc)(PyObject *lhs, PyObject *rhs);
+typedef PyObject *(*binaryopactionfunc)(PyObject *lhs, PyObject *rhs);
+
+typedef struct {
+    binaryopguardfunc guard;
+    binaryopactionfunc action;
+} _PyBinaryOpSpecializationDescr;
 
 /* Comparison bit masks. */
 
index 8b3d6285c1e4e7dfb40019ddc333c559ee41aa97..1dd155abf3babfc262313c30ddfbe55aaf973372 100644 (file)
@@ -266,6 +266,7 @@ Known values:
     Python 3.14a4 3611 (Add NOT_TAKEN instruction)
     Python 3.14a4 3612 (Add POP_ITER and INSTRUMENTED_POP_ITER)
     Python 3.14a4 3613 (Add LOAD_CONST_MORTAL instruction)
+    Python 3.14a5 3614 (Add BINARY_OP_EXTEND)
 
     Python 3.15 will start with 3650
 
@@ -278,7 +279,7 @@ PC/launcher.c must also be updated.
 
 */
 
-#define PYC_MAGIC_NUMBER 3613
+#define PYC_MAGIC_NUMBER 3614
 /* This is equivalent to converting PYC_MAGIC_NUMBER to 2 bytes
    (little-endian) and then appending b'\r\n'. */
 #define PYC_MAGIC_NUMBER_TOKEN \
index 0c0a6145bdbb27a8a10bec1d3059fe117e77139f..f7c23ad634d6be41bede64c78a1829efb7a3a7b2 100644 (file)
@@ -43,6 +43,8 @@ int _PyOpcode_num_popped(int opcode, int oparg)  {
             return 2;
         case BINARY_OP_ADD_UNICODE:
             return 2;
+        case BINARY_OP_EXTEND:
+            return 2;
         case BINARY_OP_INPLACE_ADD_UNICODE:
             return 2;
         case BINARY_OP_MULTIPLY_FLOAT:
@@ -512,6 +514,8 @@ int _PyOpcode_num_pushed(int opcode, int oparg)  {
             return 1;
         case BINARY_OP_ADD_UNICODE:
             return 1;
+        case BINARY_OP_EXTEND:
+            return 1;
         case BINARY_OP_INPLACE_ADD_UNICODE:
             return 0;
         case BINARY_OP_MULTIPLY_FLOAT:
@@ -989,6 +993,10 @@ int _PyOpcode_max_stack_effect(int opcode, int oparg, int *effect)  {
             *effect = 0;
             return 0;
         }
+        case BINARY_OP_EXTEND: {
+            *effect = 0;
+            return 0;
+        }
         case BINARY_OP_INPLACE_ADD_UNICODE: {
             *effect = 0;
             return 0;
@@ -1919,11 +1927,13 @@ enum InstructionFormat {
     INSTR_FMT_IBC = 2,
     INSTR_FMT_IBC00 = 3,
     INSTR_FMT_IBC000 = 4,
-    INSTR_FMT_IBC00000000 = 5,
-    INSTR_FMT_IX = 6,
-    INSTR_FMT_IXC = 7,
-    INSTR_FMT_IXC00 = 8,
-    INSTR_FMT_IXC000 = 9,
+    INSTR_FMT_IBC0000 = 5,
+    INSTR_FMT_IBC00000000 = 6,
+    INSTR_FMT_IX = 7,
+    INSTR_FMT_IXC = 8,
+    INSTR_FMT_IXC00 = 9,
+    INSTR_FMT_IXC000 = 10,
+    INSTR_FMT_IXC0000 = 11,
 };
 
 #define IS_VALID_OPCODE(OP) \
@@ -1981,15 +1991,16 @@ struct opcode_metadata {
 extern const struct opcode_metadata _PyOpcode_opcode_metadata[266];
 #ifdef NEED_OPCODE_METADATA
 const struct opcode_metadata _PyOpcode_opcode_metadata[266] = {
-    [BINARY_OP] = { true, INSTR_FMT_IBC, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
-    [BINARY_OP_ADD_FLOAT] = { true, INSTR_FMT_IXC, HAS_EXIT_FLAG | HAS_ERROR_FLAG },
-    [BINARY_OP_ADD_INT] = { true, INSTR_FMT_IXC, HAS_EXIT_FLAG | HAS_ERROR_FLAG },
-    [BINARY_OP_ADD_UNICODE] = { true, INSTR_FMT_IXC, HAS_EXIT_FLAG | HAS_ERROR_FLAG },
-    [BINARY_OP_INPLACE_ADD_UNICODE] = { true, INSTR_FMT_IXC, HAS_LOCAL_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG },
-    [BINARY_OP_MULTIPLY_FLOAT] = { true, INSTR_FMT_IXC, HAS_EXIT_FLAG | HAS_ERROR_FLAG },
-    [BINARY_OP_MULTIPLY_INT] = { true, INSTR_FMT_IXC, HAS_EXIT_FLAG | HAS_ERROR_FLAG },
-    [BINARY_OP_SUBTRACT_FLOAT] = { true, INSTR_FMT_IXC, HAS_EXIT_FLAG | HAS_ERROR_FLAG },
-    [BINARY_OP_SUBTRACT_INT] = { true, INSTR_FMT_IXC, HAS_EXIT_FLAG | HAS_ERROR_FLAG },
+    [BINARY_OP] = { true, INSTR_FMT_IBC0000, HAS_ARG_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
+    [BINARY_OP_ADD_FLOAT] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG | HAS_ERROR_FLAG },
+    [BINARY_OP_ADD_INT] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG | HAS_ERROR_FLAG },
+    [BINARY_OP_ADD_UNICODE] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG | HAS_ERROR_FLAG },
+    [BINARY_OP_EXTEND] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG | HAS_ESCAPES_FLAG },
+    [BINARY_OP_INPLACE_ADD_UNICODE] = { true, INSTR_FMT_IXC0000, HAS_LOCAL_FLAG | HAS_DEOPT_FLAG | HAS_EXIT_FLAG | HAS_ERROR_FLAG },
+    [BINARY_OP_MULTIPLY_FLOAT] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG | HAS_ERROR_FLAG },
+    [BINARY_OP_MULTIPLY_INT] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG | HAS_ERROR_FLAG },
+    [BINARY_OP_SUBTRACT_FLOAT] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG | HAS_ERROR_FLAG },
+    [BINARY_OP_SUBTRACT_INT] = { true, INSTR_FMT_IXC0000, HAS_EXIT_FLAG | HAS_ERROR_FLAG },
     [BINARY_SLICE] = { true, INSTR_FMT_IX, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
     [BINARY_SUBSCR] = { true, INSTR_FMT_IXC, HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
     [BINARY_SUBSCR_DICT] = { true, INSTR_FMT_IXC, HAS_DEOPT_FLAG | HAS_ERROR_FLAG | HAS_ESCAPES_FLAG },
@@ -2227,6 +2238,7 @@ _PyOpcode_macro_expansion[256] = {
     [BINARY_OP_ADD_FLOAT] = { .nuops = 2, .uops = { { _GUARD_BOTH_FLOAT, 0, 0 }, { _BINARY_OP_ADD_FLOAT, 0, 0 } } },
     [BINARY_OP_ADD_INT] = { .nuops = 2, .uops = { { _GUARD_BOTH_INT, 0, 0 }, { _BINARY_OP_ADD_INT, 0, 0 } } },
     [BINARY_OP_ADD_UNICODE] = { .nuops = 2, .uops = { { _GUARD_BOTH_UNICODE, 0, 0 }, { _BINARY_OP_ADD_UNICODE, 0, 0 } } },
+    [BINARY_OP_EXTEND] = { .nuops = 2, .uops = { { _GUARD_BINARY_OP_EXTEND, 4, 1 }, { _BINARY_OP_EXTEND, 4, 1 } } },
     [BINARY_OP_INPLACE_ADD_UNICODE] = { .nuops = 2, .uops = { { _GUARD_BOTH_UNICODE, 0, 0 }, { _BINARY_OP_INPLACE_ADD_UNICODE, 0, 0 } } },
     [BINARY_OP_MULTIPLY_FLOAT] = { .nuops = 2, .uops = { { _GUARD_BOTH_FLOAT, 0, 0 }, { _BINARY_OP_MULTIPLY_FLOAT, 0, 0 } } },
     [BINARY_OP_MULTIPLY_INT] = { .nuops = 2, .uops = { { _GUARD_BOTH_INT, 0, 0 }, { _BINARY_OP_MULTIPLY_INT, 0, 0 } } },
@@ -2411,6 +2423,7 @@ const char *_PyOpcode_OpName[266] = {
     [BINARY_OP_ADD_FLOAT] = "BINARY_OP_ADD_FLOAT",
     [BINARY_OP_ADD_INT] = "BINARY_OP_ADD_INT",
     [BINARY_OP_ADD_UNICODE] = "BINARY_OP_ADD_UNICODE",
+    [BINARY_OP_EXTEND] = "BINARY_OP_EXTEND",
     [BINARY_OP_INPLACE_ADD_UNICODE] = "BINARY_OP_INPLACE_ADD_UNICODE",
     [BINARY_OP_MULTIPLY_FLOAT] = "BINARY_OP_MULTIPLY_FLOAT",
     [BINARY_OP_MULTIPLY_INT] = "BINARY_OP_MULTIPLY_INT",
@@ -2661,7 +2674,7 @@ const uint8_t _PyOpcode_Caches[256] = {
     [FOR_ITER] = 1,
     [CALL] = 3,
     [CALL_KW] = 3,
-    [BINARY_OP] = 1,
+    [BINARY_OP] = 5,
 };
 #endif
 
@@ -2672,6 +2685,7 @@ const uint8_t _PyOpcode_Deopt[256] = {
     [BINARY_OP_ADD_FLOAT] = BINARY_OP,
     [BINARY_OP_ADD_INT] = BINARY_OP,
     [BINARY_OP_ADD_UNICODE] = BINARY_OP,
+    [BINARY_OP_EXTEND] = BINARY_OP,
     [BINARY_OP_INPLACE_ADD_UNICODE] = BINARY_OP,
     [BINARY_OP_MULTIPLY_FLOAT] = BINARY_OP,
     [BINARY_OP_MULTIPLY_INT] = BINARY_OP,
@@ -2923,7 +2937,6 @@ const uint8_t _PyOpcode_Deopt[256] = {
     case 146: \
     case 147: \
     case 148: \
-    case 229: \
     case 230: \
     case 231: \
     case 232: \
index 3841363b411eedb4dfd2e58ffeb1834e1088985b..f95defbc364aedde24e5ade389f2080af71af342 100644 (file)
@@ -15,16 +15,17 @@ extern "C" {
 #define _BINARY_OP_ADD_FLOAT 303
 #define _BINARY_OP_ADD_INT 304
 #define _BINARY_OP_ADD_UNICODE 305
-#define _BINARY_OP_INPLACE_ADD_UNICODE 306
-#define _BINARY_OP_MULTIPLY_FLOAT 307
-#define _BINARY_OP_MULTIPLY_INT 308
-#define _BINARY_OP_SUBTRACT_FLOAT 309
-#define _BINARY_OP_SUBTRACT_INT 310
-#define _BINARY_SLICE 311
-#define _BINARY_SUBSCR 312
-#define _BINARY_SUBSCR_CHECK_FUNC 313
+#define _BINARY_OP_EXTEND 306
+#define _BINARY_OP_INPLACE_ADD_UNICODE 307
+#define _BINARY_OP_MULTIPLY_FLOAT 308
+#define _BINARY_OP_MULTIPLY_INT 309
+#define _BINARY_OP_SUBTRACT_FLOAT 310
+#define _BINARY_OP_SUBTRACT_INT 311
+#define _BINARY_SLICE 312
+#define _BINARY_SUBSCR 313
+#define _BINARY_SUBSCR_CHECK_FUNC 314
 #define _BINARY_SUBSCR_DICT BINARY_SUBSCR_DICT
-#define _BINARY_SUBSCR_INIT_CALL 314
+#define _BINARY_SUBSCR_INIT_CALL 315
 #define _BINARY_SUBSCR_LIST_INT BINARY_SUBSCR_LIST_INT
 #define _BINARY_SUBSCR_STR_INT BINARY_SUBSCR_STR_INT
 #define _BINARY_SUBSCR_TUPLE_INT BINARY_SUBSCR_TUPLE_INT
@@ -34,122 +35,123 @@ extern "C" {
 #define _BUILD_SLICE BUILD_SLICE
 #define _BUILD_STRING BUILD_STRING
 #define _BUILD_TUPLE BUILD_TUPLE
-#define _CALL_BUILTIN_CLASS 315
-#define _CALL_BUILTIN_FAST 316
-#define _CALL_BUILTIN_FAST_WITH_KEYWORDS 317
-#define _CALL_BUILTIN_O 318
+#define _CALL_BUILTIN_CLASS 316
+#define _CALL_BUILTIN_FAST 317
+#define _CALL_BUILTIN_FAST_WITH_KEYWORDS 318
+#define _CALL_BUILTIN_O 319
 #define _CALL_INTRINSIC_1 CALL_INTRINSIC_1
 #define _CALL_INTRINSIC_2 CALL_INTRINSIC_2
 #define _CALL_ISINSTANCE CALL_ISINSTANCE
-#define _CALL_KW_NON_PY 319
+#define _CALL_KW_NON_PY 320
 #define _CALL_LEN CALL_LEN
 #define _CALL_LIST_APPEND CALL_LIST_APPEND
-#define _CALL_METHOD_DESCRIPTOR_FAST 320
-#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 321
-#define _CALL_METHOD_DESCRIPTOR_NOARGS 322
-#define _CALL_METHOD_DESCRIPTOR_O 323
-#define _CALL_NON_PY_GENERAL 324
-#define _CALL_STR_1 325
-#define _CALL_TUPLE_1 326
+#define _CALL_METHOD_DESCRIPTOR_FAST 321
+#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 322
+#define _CALL_METHOD_DESCRIPTOR_NOARGS 323
+#define _CALL_METHOD_DESCRIPTOR_O 324
+#define _CALL_NON_PY_GENERAL 325
+#define _CALL_STR_1 326
+#define _CALL_TUPLE_1 327
 #define _CALL_TYPE_1 CALL_TYPE_1
-#define _CHECK_AND_ALLOCATE_OBJECT 327
-#define _CHECK_ATTR_CLASS 328
-#define _CHECK_ATTR_METHOD_LAZY_DICT 329
-#define _CHECK_ATTR_MODULE_PUSH_KEYS 330
-#define _CHECK_ATTR_WITH_HINT 331
-#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS 332
+#define _CHECK_AND_ALLOCATE_OBJECT 328
+#define _CHECK_ATTR_CLASS 329
+#define _CHECK_ATTR_METHOD_LAZY_DICT 330
+#define _CHECK_ATTR_MODULE_PUSH_KEYS 331
+#define _CHECK_ATTR_WITH_HINT 332
+#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS 333
 #define _CHECK_EG_MATCH CHECK_EG_MATCH
 #define _CHECK_EXC_MATCH CHECK_EXC_MATCH
-#define _CHECK_FUNCTION 333
-#define _CHECK_FUNCTION_EXACT_ARGS 334
-#define _CHECK_FUNCTION_VERSION 335
-#define _CHECK_FUNCTION_VERSION_INLINE 336
-#define _CHECK_FUNCTION_VERSION_KW 337
-#define _CHECK_IS_NOT_PY_CALLABLE 338
-#define _CHECK_IS_NOT_PY_CALLABLE_KW 339
-#define _CHECK_MANAGED_OBJECT_HAS_VALUES 340
-#define _CHECK_METHOD_VERSION 341
-#define _CHECK_METHOD_VERSION_KW 342
-#define _CHECK_PEP_523 343
-#define _CHECK_PERIODIC 344
-#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM 345
-#define _CHECK_STACK_SPACE 346
-#define _CHECK_STACK_SPACE_OPERAND 347
-#define _CHECK_VALIDITY 348
-#define _CHECK_VALIDITY_AND_SET_IP 349
-#define _COMPARE_OP 350
-#define _COMPARE_OP_FLOAT 351
-#define _COMPARE_OP_INT 352
-#define _COMPARE_OP_STR 353
-#define _CONTAINS_OP 354
+#define _CHECK_FUNCTION 334
+#define _CHECK_FUNCTION_EXACT_ARGS 335
+#define _CHECK_FUNCTION_VERSION 336
+#define _CHECK_FUNCTION_VERSION_INLINE 337
+#define _CHECK_FUNCTION_VERSION_KW 338
+#define _CHECK_IS_NOT_PY_CALLABLE 339
+#define _CHECK_IS_NOT_PY_CALLABLE_KW 340
+#define _CHECK_MANAGED_OBJECT_HAS_VALUES 341
+#define _CHECK_METHOD_VERSION 342
+#define _CHECK_METHOD_VERSION_KW 343
+#define _CHECK_PEP_523 344
+#define _CHECK_PERIODIC 345
+#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM 346
+#define _CHECK_STACK_SPACE 347
+#define _CHECK_STACK_SPACE_OPERAND 348
+#define _CHECK_VALIDITY 349
+#define _CHECK_VALIDITY_AND_SET_IP 350
+#define _COMPARE_OP 351
+#define _COMPARE_OP_FLOAT 352
+#define _COMPARE_OP_INT 353
+#define _COMPARE_OP_STR 354
+#define _CONTAINS_OP 355
 #define _CONTAINS_OP_DICT CONTAINS_OP_DICT
 #define _CONTAINS_OP_SET CONTAINS_OP_SET
 #define _CONVERT_VALUE CONVERT_VALUE
 #define _COPY COPY
 #define _COPY_FREE_VARS COPY_FREE_VARS
-#define _CREATE_INIT_FRAME 355
+#define _CREATE_INIT_FRAME 356
 #define _DELETE_ATTR DELETE_ATTR
 #define _DELETE_DEREF DELETE_DEREF
 #define _DELETE_FAST DELETE_FAST
 #define _DELETE_GLOBAL DELETE_GLOBAL
 #define _DELETE_NAME DELETE_NAME
 #define _DELETE_SUBSCR DELETE_SUBSCR
-#define _DEOPT 356
+#define _DEOPT 357
 #define _DICT_MERGE DICT_MERGE
 #define _DICT_UPDATE DICT_UPDATE
-#define _DO_CALL 357
-#define _DO_CALL_FUNCTION_EX 358
-#define _DO_CALL_KW 359
-#define _DYNAMIC_EXIT 360
+#define _DO_CALL 358
+#define _DO_CALL_FUNCTION_EX 359
+#define _DO_CALL_KW 360
+#define _DYNAMIC_EXIT 361
 #define _END_FOR END_FOR
 #define _END_SEND END_SEND
-#define _ERROR_POP_N 361
+#define _ERROR_POP_N 362
 #define _EXIT_INIT_CHECK EXIT_INIT_CHECK
-#define _EXPAND_METHOD 362
-#define _EXPAND_METHOD_KW 363
-#define _FATAL_ERROR 364
+#define _EXPAND_METHOD 363
+#define _EXPAND_METHOD_KW 364
+#define _FATAL_ERROR 365
 #define _FORMAT_SIMPLE FORMAT_SIMPLE
 #define _FORMAT_WITH_SPEC FORMAT_WITH_SPEC
-#define _FOR_ITER 365
-#define _FOR_ITER_GEN_FRAME 366
-#define _FOR_ITER_TIER_TWO 367
+#define _FOR_ITER 366
+#define _FOR_ITER_GEN_FRAME 367
+#define _FOR_ITER_TIER_TWO 368
 #define _GET_AITER GET_AITER
 #define _GET_ANEXT GET_ANEXT
 #define _GET_AWAITABLE GET_AWAITABLE
 #define _GET_ITER GET_ITER
 #define _GET_LEN GET_LEN
 #define _GET_YIELD_FROM_ITER GET_YIELD_FROM_ITER
-#define _GUARD_BOTH_FLOAT 368
-#define _GUARD_BOTH_INT 369
-#define _GUARD_BOTH_UNICODE 370
-#define _GUARD_BUILTINS_VERSION_PUSH_KEYS 371
-#define _GUARD_DORV_NO_DICT 372
-#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 373
-#define _GUARD_GLOBALS_VERSION 374
-#define _GUARD_GLOBALS_VERSION_PUSH_KEYS 375
-#define _GUARD_IS_FALSE_POP 376
-#define _GUARD_IS_NONE_POP 377
-#define _GUARD_IS_NOT_NONE_POP 378
-#define _GUARD_IS_TRUE_POP 379
-#define _GUARD_KEYS_VERSION 380
-#define _GUARD_NOS_FLOAT 381
-#define _GUARD_NOS_INT 382
-#define _GUARD_NOT_EXHAUSTED_LIST 383
-#define _GUARD_NOT_EXHAUSTED_RANGE 384
-#define _GUARD_NOT_EXHAUSTED_TUPLE 385
-#define _GUARD_TOS_FLOAT 386
-#define _GUARD_TOS_INT 387
-#define _GUARD_TYPE_VERSION 388
-#define _GUARD_TYPE_VERSION_AND_LOCK 389
+#define _GUARD_BINARY_OP_EXTEND 369
+#define _GUARD_BOTH_FLOAT 370
+#define _GUARD_BOTH_INT 371
+#define _GUARD_BOTH_UNICODE 372
+#define _GUARD_BUILTINS_VERSION_PUSH_KEYS 373
+#define _GUARD_DORV_NO_DICT 374
+#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 375
+#define _GUARD_GLOBALS_VERSION 376
+#define _GUARD_GLOBALS_VERSION_PUSH_KEYS 377
+#define _GUARD_IS_FALSE_POP 378
+#define _GUARD_IS_NONE_POP 379
+#define _GUARD_IS_NOT_NONE_POP 380
+#define _GUARD_IS_TRUE_POP 381
+#define _GUARD_KEYS_VERSION 382
+#define _GUARD_NOS_FLOAT 383
+#define _GUARD_NOS_INT 384
+#define _GUARD_NOT_EXHAUSTED_LIST 385
+#define _GUARD_NOT_EXHAUSTED_RANGE 386
+#define _GUARD_NOT_EXHAUSTED_TUPLE 387
+#define _GUARD_TOS_FLOAT 388
+#define _GUARD_TOS_INT 389
+#define _GUARD_TYPE_VERSION 390
+#define _GUARD_TYPE_VERSION_AND_LOCK 391
 #define _IMPORT_FROM IMPORT_FROM
 #define _IMPORT_NAME IMPORT_NAME
-#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 390
-#define _INIT_CALL_PY_EXACT_ARGS 391
-#define _INIT_CALL_PY_EXACT_ARGS_0 392
-#define _INIT_CALL_PY_EXACT_ARGS_1 393
-#define _INIT_CALL_PY_EXACT_ARGS_2 394
-#define _INIT_CALL_PY_EXACT_ARGS_3 395
-#define _INIT_CALL_PY_EXACT_ARGS_4 396
+#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 392
+#define _INIT_CALL_PY_EXACT_ARGS 393
+#define _INIT_CALL_PY_EXACT_ARGS_0 394
+#define _INIT_CALL_PY_EXACT_ARGS_1 395
+#define _INIT_CALL_PY_EXACT_ARGS_2 396
+#define _INIT_CALL_PY_EXACT_ARGS_3 397
+#define _INIT_CALL_PY_EXACT_ARGS_4 398
 #define _INSTRUMENTED_CALL_FUNCTION_EX INSTRUMENTED_CALL_FUNCTION_EX
 #define _INSTRUMENTED_CALL_KW INSTRUMENTED_CALL_KW
 #define _INSTRUMENTED_FOR_ITER INSTRUMENTED_FOR_ITER
@@ -162,144 +164,144 @@ extern "C" {
 #define _INSTRUMENTED_POP_JUMP_IF_NONE INSTRUMENTED_POP_JUMP_IF_NONE
 #define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE INSTRUMENTED_POP_JUMP_IF_NOT_NONE
 #define _INSTRUMENTED_POP_JUMP_IF_TRUE INSTRUMENTED_POP_JUMP_IF_TRUE
-#define _INTERNAL_INCREMENT_OPT_COUNTER 397
-#define _IS_NONE 398
+#define _INTERNAL_INCREMENT_OPT_COUNTER 399
+#define _IS_NONE 400
 #define _IS_OP IS_OP
-#define _ITER_CHECK_LIST 399
-#define _ITER_CHECK_RANGE 400
-#define _ITER_CHECK_TUPLE 401
-#define _ITER_JUMP_LIST 402
-#define _ITER_JUMP_RANGE 403
-#define _ITER_JUMP_TUPLE 404
-#define _ITER_NEXT_LIST 405
-#define _ITER_NEXT_RANGE 406
-#define _ITER_NEXT_TUPLE 407
-#define _JUMP_TO_TOP 408
+#define _ITER_CHECK_LIST 401
+#define _ITER_CHECK_RANGE 402
+#define _ITER_CHECK_TUPLE 403
+#define _ITER_JUMP_LIST 404
+#define _ITER_JUMP_RANGE 405
+#define _ITER_JUMP_TUPLE 406
+#define _ITER_NEXT_LIST 407
+#define _ITER_NEXT_RANGE 408
+#define _ITER_NEXT_TUPLE 409
+#define _JUMP_TO_TOP 410
 #define _LIST_APPEND LIST_APPEND
 #define _LIST_EXTEND LIST_EXTEND
-#define _LOAD_ATTR 409
-#define _LOAD_ATTR_CLASS 410
-#define _LOAD_ATTR_CLASS_0 411
-#define _LOAD_ATTR_CLASS_1 412
+#define _LOAD_ATTR 411
+#define _LOAD_ATTR_CLASS 412
+#define _LOAD_ATTR_CLASS_0 413
+#define _LOAD_ATTR_CLASS_1 414
 #define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN
-#define _LOAD_ATTR_INSTANCE_VALUE 413
-#define _LOAD_ATTR_INSTANCE_VALUE_0 414
-#define _LOAD_ATTR_INSTANCE_VALUE_1 415
-#define _LOAD_ATTR_METHOD_LAZY_DICT 416
-#define _LOAD_ATTR_METHOD_NO_DICT 417
-#define _LOAD_ATTR_METHOD_WITH_VALUES 418
-#define _LOAD_ATTR_MODULE 419
-#define _LOAD_ATTR_MODULE_FROM_KEYS 420
-#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 421
-#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 422
-#define _LOAD_ATTR_PROPERTY_FRAME 423
-#define _LOAD_ATTR_SLOT 424
-#define _LOAD_ATTR_SLOT_0 425
-#define _LOAD_ATTR_SLOT_1 426
-#define _LOAD_ATTR_WITH_HINT 427
+#define _LOAD_ATTR_INSTANCE_VALUE 415
+#define _LOAD_ATTR_INSTANCE_VALUE_0 416
+#define _LOAD_ATTR_INSTANCE_VALUE_1 417
+#define _LOAD_ATTR_METHOD_LAZY_DICT 418
+#define _LOAD_ATTR_METHOD_NO_DICT 419
+#define _LOAD_ATTR_METHOD_WITH_VALUES 420
+#define _LOAD_ATTR_MODULE 421
+#define _LOAD_ATTR_MODULE_FROM_KEYS 422
+#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 423
+#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 424
+#define _LOAD_ATTR_PROPERTY_FRAME 425
+#define _LOAD_ATTR_SLOT 426
+#define _LOAD_ATTR_SLOT_0 427
+#define _LOAD_ATTR_SLOT_1 428
+#define _LOAD_ATTR_WITH_HINT 429
 #define _LOAD_BUILD_CLASS LOAD_BUILD_CLASS
-#define _LOAD_BYTECODE 428
+#define _LOAD_BYTECODE 430
 #define _LOAD_COMMON_CONSTANT LOAD_COMMON_CONSTANT
 #define _LOAD_CONST LOAD_CONST
 #define _LOAD_CONST_IMMORTAL LOAD_CONST_IMMORTAL
-#define _LOAD_CONST_INLINE 429
-#define _LOAD_CONST_INLINE_BORROW 430
-#define _LOAD_CONST_INLINE_BORROW_WITH_NULL 431
-#define _LOAD_CONST_INLINE_WITH_NULL 432
+#define _LOAD_CONST_INLINE 431
+#define _LOAD_CONST_INLINE_BORROW 432
+#define _LOAD_CONST_INLINE_BORROW_WITH_NULL 433
+#define _LOAD_CONST_INLINE_WITH_NULL 434
 #define _LOAD_CONST_MORTAL LOAD_CONST_MORTAL
 #define _LOAD_DEREF LOAD_DEREF
-#define _LOAD_FAST 433
-#define _LOAD_FAST_0 434
-#define _LOAD_FAST_1 435
-#define _LOAD_FAST_2 436
-#define _LOAD_FAST_3 437
-#define _LOAD_FAST_4 438
-#define _LOAD_FAST_5 439
-#define _LOAD_FAST_6 440
-#define _LOAD_FAST_7 441
+#define _LOAD_FAST 435
+#define _LOAD_FAST_0 436
+#define _LOAD_FAST_1 437
+#define _LOAD_FAST_2 438
+#define _LOAD_FAST_3 439
+#define _LOAD_FAST_4 440
+#define _LOAD_FAST_5 441
+#define _LOAD_FAST_6 442
+#define _LOAD_FAST_7 443
 #define _LOAD_FAST_AND_CLEAR LOAD_FAST_AND_CLEAR
 #define _LOAD_FAST_CHECK LOAD_FAST_CHECK
 #define _LOAD_FAST_LOAD_FAST LOAD_FAST_LOAD_FAST
 #define _LOAD_FROM_DICT_OR_DEREF LOAD_FROM_DICT_OR_DEREF
 #define _LOAD_FROM_DICT_OR_GLOBALS LOAD_FROM_DICT_OR_GLOBALS
-#define _LOAD_GLOBAL 442
-#define _LOAD_GLOBAL_BUILTINS 443
-#define _LOAD_GLOBAL_BUILTINS_FROM_KEYS 444
-#define _LOAD_GLOBAL_MODULE 445
-#define _LOAD_GLOBAL_MODULE_FROM_KEYS 446
+#define _LOAD_GLOBAL 444
+#define _LOAD_GLOBAL_BUILTINS 445
+#define _LOAD_GLOBAL_BUILTINS_FROM_KEYS 446
+#define _LOAD_GLOBAL_MODULE 447
+#define _LOAD_GLOBAL_MODULE_FROM_KEYS 448
 #define _LOAD_LOCALS LOAD_LOCALS
 #define _LOAD_NAME LOAD_NAME
-#define _LOAD_SMALL_INT 447
-#define _LOAD_SMALL_INT_0 448
-#define _LOAD_SMALL_INT_1 449
-#define _LOAD_SMALL_INT_2 450
-#define _LOAD_SMALL_INT_3 451
+#define _LOAD_SMALL_INT 449
+#define _LOAD_SMALL_INT_0 450
+#define _LOAD_SMALL_INT_1 451
+#define _LOAD_SMALL_INT_2 452
+#define _LOAD_SMALL_INT_3 453
 #define _LOAD_SPECIAL LOAD_SPECIAL
 #define _LOAD_SUPER_ATTR_ATTR LOAD_SUPER_ATTR_ATTR
 #define _LOAD_SUPER_ATTR_METHOD LOAD_SUPER_ATTR_METHOD
-#define _MAKE_CALLARGS_A_TUPLE 452
+#define _MAKE_CALLARGS_A_TUPLE 454
 #define _MAKE_CELL MAKE_CELL
 #define _MAKE_FUNCTION MAKE_FUNCTION
-#define _MAKE_WARM 453
+#define _MAKE_WARM 455
 #define _MAP_ADD MAP_ADD
 #define _MATCH_CLASS MATCH_CLASS
 #define _MATCH_KEYS MATCH_KEYS
 #define _MATCH_MAPPING MATCH_MAPPING
 #define _MATCH_SEQUENCE MATCH_SEQUENCE
-#define _MAYBE_EXPAND_METHOD 454
-#define _MAYBE_EXPAND_METHOD_KW 455
-#define _MONITOR_CALL 456
-#define _MONITOR_JUMP_BACKWARD 457
-#define _MONITOR_RESUME 458
+#define _MAYBE_EXPAND_METHOD 456
+#define _MAYBE_EXPAND_METHOD_KW 457
+#define _MONITOR_CALL 458
+#define _MONITOR_JUMP_BACKWARD 459
+#define _MONITOR_RESUME 460
 #define _NOP NOP
 #define _POP_EXCEPT POP_EXCEPT
-#define _POP_JUMP_IF_FALSE 459
-#define _POP_JUMP_IF_TRUE 460
+#define _POP_JUMP_IF_FALSE 461
+#define _POP_JUMP_IF_TRUE 462
 #define _POP_TOP POP_TOP
-#define _POP_TOP_LOAD_CONST_INLINE_BORROW 461
+#define _POP_TOP_LOAD_CONST_INLINE_BORROW 463
 #define _PUSH_EXC_INFO PUSH_EXC_INFO
-#define _PUSH_FRAME 462
+#define _PUSH_FRAME 464
 #define _PUSH_NULL PUSH_NULL
-#define _PY_FRAME_GENERAL 463
-#define _PY_FRAME_KW 464
-#define _QUICKEN_RESUME 465
-#define _REPLACE_WITH_TRUE 466
+#define _PY_FRAME_GENERAL 465
+#define _PY_FRAME_KW 466
+#define _QUICKEN_RESUME 467
+#define _REPLACE_WITH_TRUE 468
 #define _RESUME_CHECK RESUME_CHECK
 #define _RETURN_GENERATOR RETURN_GENERATOR
 #define _RETURN_VALUE RETURN_VALUE
-#define _SAVE_RETURN_OFFSET 467
-#define _SEND 468
-#define _SEND_GEN_FRAME 469
+#define _SAVE_RETURN_OFFSET 469
+#define _SEND 470
+#define _SEND_GEN_FRAME 471
 #define _SETUP_ANNOTATIONS SETUP_ANNOTATIONS
 #define _SET_ADD SET_ADD
 #define _SET_FUNCTION_ATTRIBUTE SET_FUNCTION_ATTRIBUTE
 #define _SET_UPDATE SET_UPDATE
-#define _START_EXECUTOR 470
-#define _STORE_ATTR 471
-#define _STORE_ATTR_INSTANCE_VALUE 472
-#define _STORE_ATTR_SLOT 473
-#define _STORE_ATTR_WITH_HINT 474
+#define _START_EXECUTOR 472
+#define _STORE_ATTR 473
+#define _STORE_ATTR_INSTANCE_VALUE 474
+#define _STORE_ATTR_SLOT 475
+#define _STORE_ATTR_WITH_HINT 476
 #define _STORE_DEREF STORE_DEREF
-#define _STORE_FAST 475
-#define _STORE_FAST_0 476
-#define _STORE_FAST_1 477
-#define _STORE_FAST_2 478
-#define _STORE_FAST_3 479
-#define _STORE_FAST_4 480
-#define _STORE_FAST_5 481
-#define _STORE_FAST_6 482
-#define _STORE_FAST_7 483
+#define _STORE_FAST 477
+#define _STORE_FAST_0 478
+#define _STORE_FAST_1 479
+#define _STORE_FAST_2 480
+#define _STORE_FAST_3 481
+#define _STORE_FAST_4 482
+#define _STORE_FAST_5 483
+#define _STORE_FAST_6 484
+#define _STORE_FAST_7 485
 #define _STORE_FAST_LOAD_FAST STORE_FAST_LOAD_FAST
 #define _STORE_FAST_STORE_FAST STORE_FAST_STORE_FAST
 #define _STORE_GLOBAL STORE_GLOBAL
 #define _STORE_NAME STORE_NAME
-#define _STORE_SLICE 484
-#define _STORE_SUBSCR 485
+#define _STORE_SLICE 486
+#define _STORE_SUBSCR 487
 #define _STORE_SUBSCR_DICT STORE_SUBSCR_DICT
 #define _STORE_SUBSCR_LIST_INT STORE_SUBSCR_LIST_INT
 #define _SWAP SWAP
-#define _TIER2_RESUME_CHECK 486
-#define _TO_BOOL 487
+#define _TIER2_RESUME_CHECK 488
+#define _TO_BOOL 489
 #define _TO_BOOL_BOOL TO_BOOL_BOOL
 #define _TO_BOOL_INT TO_BOOL_INT
 #define _TO_BOOL_LIST TO_BOOL_LIST
@@ -309,13 +311,13 @@ extern "C" {
 #define _UNARY_NEGATIVE UNARY_NEGATIVE
 #define _UNARY_NOT UNARY_NOT
 #define _UNPACK_EX UNPACK_EX
-#define _UNPACK_SEQUENCE 488
+#define _UNPACK_SEQUENCE 490
 #define _UNPACK_SEQUENCE_LIST UNPACK_SEQUENCE_LIST
 #define _UNPACK_SEQUENCE_TUPLE UNPACK_SEQUENCE_TUPLE
 #define _UNPACK_SEQUENCE_TWO_TUPLE UNPACK_SEQUENCE_TWO_TUPLE
 #define _WITH_EXCEPT_START WITH_EXCEPT_START
 #define _YIELD_VALUE YIELD_VALUE
-#define MAX_UOP_ID 488
+#define MAX_UOP_ID 490
 
 #ifdef __cplusplus
 }
index 5670fe26f72071cf3e532ef3c2f4a2e13d2fcb4d..298e918b872c6227c950b6259f6722d20936a5d2 100644 (file)
@@ -82,6 +82,8 @@ const uint16_t _PyUop_Flags[MAX_UOP_ID+1] = {
     [_GUARD_BOTH_UNICODE] = HAS_EXIT_FLAG,
     [_BINARY_OP_ADD_UNICODE] = HAS_ERROR_FLAG | HAS_PURE_FLAG,
     [_BINARY_OP_INPLACE_ADD_UNICODE] = HAS_LOCAL_FLAG | HAS_DEOPT_FLAG | HAS_ERROR_FLAG,
+    [_GUARD_BINARY_OP_EXTEND] = HAS_EXIT_FLAG | HAS_ESCAPES_FLAG,
+    [_BINARY_OP_EXTEND] = HAS_ESCAPES_FLAG | HAS_PURE_FLAG,
     [_BINARY_SUBSCR] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
     [_BINARY_SLICE] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
     [_STORE_SLICE] = HAS_ERROR_FLAG | HAS_ESCAPES_FLAG,
@@ -309,6 +311,7 @@ const char *const _PyOpcode_uop_name[MAX_UOP_ID+1] = {
     [_BINARY_OP_ADD_FLOAT] = "_BINARY_OP_ADD_FLOAT",
     [_BINARY_OP_ADD_INT] = "_BINARY_OP_ADD_INT",
     [_BINARY_OP_ADD_UNICODE] = "_BINARY_OP_ADD_UNICODE",
+    [_BINARY_OP_EXTEND] = "_BINARY_OP_EXTEND",
     [_BINARY_OP_INPLACE_ADD_UNICODE] = "_BINARY_OP_INPLACE_ADD_UNICODE",
     [_BINARY_OP_MULTIPLY_FLOAT] = "_BINARY_OP_MULTIPLY_FLOAT",
     [_BINARY_OP_MULTIPLY_INT] = "_BINARY_OP_MULTIPLY_INT",
@@ -410,6 +413,7 @@ const char *const _PyOpcode_uop_name[MAX_UOP_ID+1] = {
     [_GET_ITER] = "_GET_ITER",
     [_GET_LEN] = "_GET_LEN",
     [_GET_YIELD_FROM_ITER] = "_GET_YIELD_FROM_ITER",
+    [_GUARD_BINARY_OP_EXTEND] = "_GUARD_BINARY_OP_EXTEND",
     [_GUARD_BOTH_FLOAT] = "_GUARD_BOTH_FLOAT",
     [_GUARD_BOTH_INT] = "_GUARD_BOTH_INT",
     [_GUARD_BOTH_UNICODE] = "_GUARD_BOTH_UNICODE",
@@ -711,6 +715,10 @@ int _PyUop_num_popped(int opcode, int oparg)
             return 2;
         case _BINARY_OP_INPLACE_ADD_UNICODE:
             return 2;
+        case _GUARD_BINARY_OP_EXTEND:
+            return 0;
+        case _BINARY_OP_EXTEND:
+            return 2;
         case _BINARY_SUBSCR:
             return 2;
         case _BINARY_SLICE:
index f2d8963a1813c57547c635cbccd81c9ee788aada..06b207b347e50427e3c1fda5536b3b0114829ab5 100644 (file)
@@ -132,82 +132,83 @@ extern "C" {
 #define BINARY_OP_ADD_FLOAT                    150
 #define BINARY_OP_ADD_INT                      151
 #define BINARY_OP_ADD_UNICODE                  152
-#define BINARY_OP_MULTIPLY_FLOAT               153
-#define BINARY_OP_MULTIPLY_INT                 154
-#define BINARY_OP_SUBTRACT_FLOAT               155
-#define BINARY_OP_SUBTRACT_INT                 156
-#define BINARY_SUBSCR_DICT                     157
-#define BINARY_SUBSCR_GETITEM                  158
-#define BINARY_SUBSCR_LIST_INT                 159
-#define BINARY_SUBSCR_STR_INT                  160
-#define BINARY_SUBSCR_TUPLE_INT                161
-#define CALL_ALLOC_AND_ENTER_INIT              162
-#define CALL_BOUND_METHOD_EXACT_ARGS           163
-#define CALL_BOUND_METHOD_GENERAL              164
-#define CALL_BUILTIN_CLASS                     165
-#define CALL_BUILTIN_FAST                      166
-#define CALL_BUILTIN_FAST_WITH_KEYWORDS        167
-#define CALL_BUILTIN_O                         168
-#define CALL_ISINSTANCE                        169
-#define CALL_KW_BOUND_METHOD                   170
-#define CALL_KW_NON_PY                         171
-#define CALL_KW_PY                             172
-#define CALL_LEN                               173
-#define CALL_LIST_APPEND                       174
-#define CALL_METHOD_DESCRIPTOR_FAST            175
-#define CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 176
-#define CALL_METHOD_DESCRIPTOR_NOARGS          177
-#define CALL_METHOD_DESCRIPTOR_O               178
-#define CALL_NON_PY_GENERAL                    179
-#define CALL_PY_EXACT_ARGS                     180
-#define CALL_PY_GENERAL                        181
-#define CALL_STR_1                             182
-#define CALL_TUPLE_1                           183
-#define CALL_TYPE_1                            184
-#define COMPARE_OP_FLOAT                       185
-#define COMPARE_OP_INT                         186
-#define COMPARE_OP_STR                         187
-#define CONTAINS_OP_DICT                       188
-#define CONTAINS_OP_SET                        189
-#define FOR_ITER_GEN                           190
-#define FOR_ITER_LIST                          191
-#define FOR_ITER_RANGE                         192
-#define FOR_ITER_TUPLE                         193
-#define LOAD_ATTR_CLASS                        194
-#define LOAD_ATTR_CLASS_WITH_METACLASS_CHECK   195
-#define LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN      196
-#define LOAD_ATTR_INSTANCE_VALUE               197
-#define LOAD_ATTR_METHOD_LAZY_DICT             198
-#define LOAD_ATTR_METHOD_NO_DICT               199
-#define LOAD_ATTR_METHOD_WITH_VALUES           200
-#define LOAD_ATTR_MODULE                       201
-#define LOAD_ATTR_NONDESCRIPTOR_NO_DICT        202
-#define LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES    203
-#define LOAD_ATTR_PROPERTY                     204
-#define LOAD_ATTR_SLOT                         205
-#define LOAD_ATTR_WITH_HINT                    206
-#define LOAD_CONST_IMMORTAL                    207
-#define LOAD_CONST_MORTAL                      208
-#define LOAD_GLOBAL_BUILTIN                    209
-#define LOAD_GLOBAL_MODULE                     210
-#define LOAD_SUPER_ATTR_ATTR                   211
-#define LOAD_SUPER_ATTR_METHOD                 212
-#define RESUME_CHECK                           213
-#define SEND_GEN                               214
-#define STORE_ATTR_INSTANCE_VALUE              215
-#define STORE_ATTR_SLOT                        216
-#define STORE_ATTR_WITH_HINT                   217
-#define STORE_SUBSCR_DICT                      218
-#define STORE_SUBSCR_LIST_INT                  219
-#define TO_BOOL_ALWAYS_TRUE                    220
-#define TO_BOOL_BOOL                           221
-#define TO_BOOL_INT                            222
-#define TO_BOOL_LIST                           223
-#define TO_BOOL_NONE                           224
-#define TO_BOOL_STR                            225
-#define UNPACK_SEQUENCE_LIST                   226
-#define UNPACK_SEQUENCE_TUPLE                  227
-#define UNPACK_SEQUENCE_TWO_TUPLE              228
+#define BINARY_OP_EXTEND                       153
+#define BINARY_OP_MULTIPLY_FLOAT               154
+#define BINARY_OP_MULTIPLY_INT                 155
+#define BINARY_OP_SUBTRACT_FLOAT               156
+#define BINARY_OP_SUBTRACT_INT                 157
+#define BINARY_SUBSCR_DICT                     158
+#define BINARY_SUBSCR_GETITEM                  159
+#define BINARY_SUBSCR_LIST_INT                 160
+#define BINARY_SUBSCR_STR_INT                  161
+#define BINARY_SUBSCR_TUPLE_INT                162
+#define CALL_ALLOC_AND_ENTER_INIT              163
+#define CALL_BOUND_METHOD_EXACT_ARGS           164
+#define CALL_BOUND_METHOD_GENERAL              165
+#define CALL_BUILTIN_CLASS                     166
+#define CALL_BUILTIN_FAST                      167
+#define CALL_BUILTIN_FAST_WITH_KEYWORDS        168
+#define CALL_BUILTIN_O                         169
+#define CALL_ISINSTANCE                        170
+#define CALL_KW_BOUND_METHOD                   171
+#define CALL_KW_NON_PY                         172
+#define CALL_KW_PY                             173
+#define CALL_LEN                               174
+#define CALL_LIST_APPEND                       175
+#define CALL_METHOD_DESCRIPTOR_FAST            176
+#define CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 177
+#define CALL_METHOD_DESCRIPTOR_NOARGS          178
+#define CALL_METHOD_DESCRIPTOR_O               179
+#define CALL_NON_PY_GENERAL                    180
+#define CALL_PY_EXACT_ARGS                     181
+#define CALL_PY_GENERAL                        182
+#define CALL_STR_1                             183
+#define CALL_TUPLE_1                           184
+#define CALL_TYPE_1                            185
+#define COMPARE_OP_FLOAT                       186
+#define COMPARE_OP_INT                         187
+#define COMPARE_OP_STR                         188
+#define CONTAINS_OP_DICT                       189
+#define CONTAINS_OP_SET                        190
+#define FOR_ITER_GEN                           191
+#define FOR_ITER_LIST                          192
+#define FOR_ITER_RANGE                         193
+#define FOR_ITER_TUPLE                         194
+#define LOAD_ATTR_CLASS                        195
+#define LOAD_ATTR_CLASS_WITH_METACLASS_CHECK   196
+#define LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN      197
+#define LOAD_ATTR_INSTANCE_VALUE               198
+#define LOAD_ATTR_METHOD_LAZY_DICT             199
+#define LOAD_ATTR_METHOD_NO_DICT               200
+#define LOAD_ATTR_METHOD_WITH_VALUES           201
+#define LOAD_ATTR_MODULE                       202
+#define LOAD_ATTR_NONDESCRIPTOR_NO_DICT        203
+#define LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES    204
+#define LOAD_ATTR_PROPERTY                     205
+#define LOAD_ATTR_SLOT                         206
+#define LOAD_ATTR_WITH_HINT                    207
+#define LOAD_CONST_IMMORTAL                    208
+#define LOAD_CONST_MORTAL                      209
+#define LOAD_GLOBAL_BUILTIN                    210
+#define LOAD_GLOBAL_MODULE                     211
+#define LOAD_SUPER_ATTR_ATTR                   212
+#define LOAD_SUPER_ATTR_METHOD                 213
+#define RESUME_CHECK                           214
+#define SEND_GEN                               215
+#define STORE_ATTR_INSTANCE_VALUE              216
+#define STORE_ATTR_SLOT                        217
+#define STORE_ATTR_WITH_HINT                   218
+#define STORE_SUBSCR_DICT                      219
+#define STORE_SUBSCR_LIST_INT                  220
+#define TO_BOOL_ALWAYS_TRUE                    221
+#define TO_BOOL_BOOL                           222
+#define TO_BOOL_INT                            223
+#define TO_BOOL_LIST                           224
+#define TO_BOOL_NONE                           225
+#define TO_BOOL_STR                            226
+#define UNPACK_SEQUENCE_LIST                   227
+#define UNPACK_SEQUENCE_TUPLE                  228
+#define UNPACK_SEQUENCE_TWO_TUPLE              229
 #define INSTRUMENTED_END_FOR                   235
 #define INSTRUMENTED_POP_ITER                  236
 #define INSTRUMENTED_END_SEND                  237
index d93e8d8df8fe4bfb3fd3d19e5d300561ec21b7b8..7dd528ef74df3362b628b81a70ea891e9b8e7510 100644 (file)
@@ -26,6 +26,7 @@ _specializations = {
         "BINARY_OP_ADD_FLOAT",
         "BINARY_OP_SUBTRACT_FLOAT",
         "BINARY_OP_ADD_UNICODE",
+        "BINARY_OP_EXTEND",
         "BINARY_OP_INPLACE_ADD_UNICODE",
     ],
     "BINARY_SUBSCR": [
@@ -123,83 +124,84 @@ _specialized_opmap = {
     'BINARY_OP_ADD_FLOAT': 150,
     'BINARY_OP_ADD_INT': 151,
     'BINARY_OP_ADD_UNICODE': 152,
+    'BINARY_OP_EXTEND': 153,
     'BINARY_OP_INPLACE_ADD_UNICODE': 3,
-    'BINARY_OP_MULTIPLY_FLOAT': 153,
-    'BINARY_OP_MULTIPLY_INT': 154,
-    'BINARY_OP_SUBTRACT_FLOAT': 155,
-    'BINARY_OP_SUBTRACT_INT': 156,
-    'BINARY_SUBSCR_DICT': 157,
-    'BINARY_SUBSCR_GETITEM': 158,
-    'BINARY_SUBSCR_LIST_INT': 159,
-    'BINARY_SUBSCR_STR_INT': 160,
-    'BINARY_SUBSCR_TUPLE_INT': 161,
-    'CALL_ALLOC_AND_ENTER_INIT': 162,
-    'CALL_BOUND_METHOD_EXACT_ARGS': 163,
-    'CALL_BOUND_METHOD_GENERAL': 164,
-    'CALL_BUILTIN_CLASS': 165,
-    'CALL_BUILTIN_FAST': 166,
-    'CALL_BUILTIN_FAST_WITH_KEYWORDS': 167,
-    'CALL_BUILTIN_O': 168,
-    'CALL_ISINSTANCE': 169,
-    'CALL_KW_BOUND_METHOD': 170,
-    'CALL_KW_NON_PY': 171,
-    'CALL_KW_PY': 172,
-    'CALL_LEN': 173,
-    'CALL_LIST_APPEND': 174,
-    'CALL_METHOD_DESCRIPTOR_FAST': 175,
-    'CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS': 176,
-    'CALL_METHOD_DESCRIPTOR_NOARGS': 177,
-    'CALL_METHOD_DESCRIPTOR_O': 178,
-    'CALL_NON_PY_GENERAL': 179,
-    'CALL_PY_EXACT_ARGS': 180,
-    'CALL_PY_GENERAL': 181,
-    'CALL_STR_1': 182,
-    'CALL_TUPLE_1': 183,
-    'CALL_TYPE_1': 184,
-    'COMPARE_OP_FLOAT': 185,
-    'COMPARE_OP_INT': 186,
-    'COMPARE_OP_STR': 187,
-    'CONTAINS_OP_DICT': 188,
-    'CONTAINS_OP_SET': 189,
-    'FOR_ITER_GEN': 190,
-    'FOR_ITER_LIST': 191,
-    'FOR_ITER_RANGE': 192,
-    'FOR_ITER_TUPLE': 193,
-    'LOAD_ATTR_CLASS': 194,
-    'LOAD_ATTR_CLASS_WITH_METACLASS_CHECK': 195,
-    'LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN': 196,
-    'LOAD_ATTR_INSTANCE_VALUE': 197,
-    'LOAD_ATTR_METHOD_LAZY_DICT': 198,
-    'LOAD_ATTR_METHOD_NO_DICT': 199,
-    'LOAD_ATTR_METHOD_WITH_VALUES': 200,
-    'LOAD_ATTR_MODULE': 201,
-    'LOAD_ATTR_NONDESCRIPTOR_NO_DICT': 202,
-    'LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES': 203,
-    'LOAD_ATTR_PROPERTY': 204,
-    'LOAD_ATTR_SLOT': 205,
-    'LOAD_ATTR_WITH_HINT': 206,
-    'LOAD_CONST_IMMORTAL': 207,
-    'LOAD_CONST_MORTAL': 208,
-    'LOAD_GLOBAL_BUILTIN': 209,
-    'LOAD_GLOBAL_MODULE': 210,
-    'LOAD_SUPER_ATTR_ATTR': 211,
-    'LOAD_SUPER_ATTR_METHOD': 212,
-    'RESUME_CHECK': 213,
-    'SEND_GEN': 214,
-    'STORE_ATTR_INSTANCE_VALUE': 215,
-    'STORE_ATTR_SLOT': 216,
-    'STORE_ATTR_WITH_HINT': 217,
-    'STORE_SUBSCR_DICT': 218,
-    'STORE_SUBSCR_LIST_INT': 219,
-    'TO_BOOL_ALWAYS_TRUE': 220,
-    'TO_BOOL_BOOL': 221,
-    'TO_BOOL_INT': 222,
-    'TO_BOOL_LIST': 223,
-    'TO_BOOL_NONE': 224,
-    'TO_BOOL_STR': 225,
-    'UNPACK_SEQUENCE_LIST': 226,
-    'UNPACK_SEQUENCE_TUPLE': 227,
-    'UNPACK_SEQUENCE_TWO_TUPLE': 228,
+    'BINARY_OP_MULTIPLY_FLOAT': 154,
+    'BINARY_OP_MULTIPLY_INT': 155,
+    'BINARY_OP_SUBTRACT_FLOAT': 156,
+    'BINARY_OP_SUBTRACT_INT': 157,
+    'BINARY_SUBSCR_DICT': 158,
+    'BINARY_SUBSCR_GETITEM': 159,
+    'BINARY_SUBSCR_LIST_INT': 160,
+    'BINARY_SUBSCR_STR_INT': 161,
+    'BINARY_SUBSCR_TUPLE_INT': 162,
+    'CALL_ALLOC_AND_ENTER_INIT': 163,
+    'CALL_BOUND_METHOD_EXACT_ARGS': 164,
+    'CALL_BOUND_METHOD_GENERAL': 165,
+    'CALL_BUILTIN_CLASS': 166,
+    'CALL_BUILTIN_FAST': 167,
+    'CALL_BUILTIN_FAST_WITH_KEYWORDS': 168,
+    'CALL_BUILTIN_O': 169,
+    'CALL_ISINSTANCE': 170,
+    'CALL_KW_BOUND_METHOD': 171,
+    'CALL_KW_NON_PY': 172,
+    'CALL_KW_PY': 173,
+    'CALL_LEN': 174,
+    'CALL_LIST_APPEND': 175,
+    'CALL_METHOD_DESCRIPTOR_FAST': 176,
+    'CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS': 177,
+    'CALL_METHOD_DESCRIPTOR_NOARGS': 178,
+    'CALL_METHOD_DESCRIPTOR_O': 179,
+    'CALL_NON_PY_GENERAL': 180,
+    'CALL_PY_EXACT_ARGS': 181,
+    'CALL_PY_GENERAL': 182,
+    'CALL_STR_1': 183,
+    'CALL_TUPLE_1': 184,
+    'CALL_TYPE_1': 185,
+    'COMPARE_OP_FLOAT': 186,
+    'COMPARE_OP_INT': 187,
+    'COMPARE_OP_STR': 188,
+    'CONTAINS_OP_DICT': 189,
+    'CONTAINS_OP_SET': 190,
+    'FOR_ITER_GEN': 191,
+    'FOR_ITER_LIST': 192,
+    'FOR_ITER_RANGE': 193,
+    'FOR_ITER_TUPLE': 194,
+    'LOAD_ATTR_CLASS': 195,
+    'LOAD_ATTR_CLASS_WITH_METACLASS_CHECK': 196,
+    'LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN': 197,
+    'LOAD_ATTR_INSTANCE_VALUE': 198,
+    'LOAD_ATTR_METHOD_LAZY_DICT': 199,
+    'LOAD_ATTR_METHOD_NO_DICT': 200,
+    'LOAD_ATTR_METHOD_WITH_VALUES': 201,
+    'LOAD_ATTR_MODULE': 202,
+    'LOAD_ATTR_NONDESCRIPTOR_NO_DICT': 203,
+    'LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES': 204,
+    'LOAD_ATTR_PROPERTY': 205,
+    'LOAD_ATTR_SLOT': 206,
+    'LOAD_ATTR_WITH_HINT': 207,
+    'LOAD_CONST_IMMORTAL': 208,
+    'LOAD_CONST_MORTAL': 209,
+    'LOAD_GLOBAL_BUILTIN': 210,
+    'LOAD_GLOBAL_MODULE': 211,
+    'LOAD_SUPER_ATTR_ATTR': 212,
+    'LOAD_SUPER_ATTR_METHOD': 213,
+    'RESUME_CHECK': 214,
+    'SEND_GEN': 215,
+    'STORE_ATTR_INSTANCE_VALUE': 216,
+    'STORE_ATTR_SLOT': 217,
+    'STORE_ATTR_WITH_HINT': 218,
+    'STORE_SUBSCR_DICT': 219,
+    'STORE_SUBSCR_LIST_INT': 220,
+    'TO_BOOL_ALWAYS_TRUE': 221,
+    'TO_BOOL_BOOL': 222,
+    'TO_BOOL_INT': 223,
+    'TO_BOOL_LIST': 224,
+    'TO_BOOL_NONE': 225,
+    'TO_BOOL_STR': 226,
+    'UNPACK_SEQUENCE_LIST': 227,
+    'UNPACK_SEQUENCE_TUPLE': 228,
+    'UNPACK_SEQUENCE_TWO_TUPLE': 229,
 }
 
 opmap = {
index aba66153af1b2e7671853f665c06db05ec6f0fbe..4ee0d64026bd0a19eea9268ddef2151986565217 100644 (file)
@@ -52,6 +52,7 @@ _cache_format = {
     },
     "BINARY_OP": {
         "counter": 1,
+        "descr": 4,
     },
     "UNPACK_SEQUENCE": {
         "counter": 1,
index 7ffa4eb8639add9358d1e7c49f7645505bce75ea..69c1ee0690d269126f042d76292ffc68792e65cb 100644 (file)
@@ -429,14 +429,14 @@ class CodeTest(unittest.TestCase):
         def foo():
             pass
 
-        # assert that opcode 229 is invalid
-        self.assertEqual(opname[229], '<229>')
+        # assert that opcode 135 is invalid
+        self.assertEqual(opname[135], '<135>')
 
-        # change first opcode to 0xeb (=229)
+        # change first opcode to 0x87 (=135)
         foo.__code__ = foo.__code__.replace(
-            co_code=b'\xe5' + foo.__code__.co_code[1:])
+            co_code=b'\x87' + foo.__code__.co_code[1:])
 
-        msg = "unknown opcode 229"
+        msg = "unknown opcode 135"
         with self.assertRaisesRegex(SystemError, msg):
             foo()
 
index 8afe9653f19f6ea8a7b061e6cf8dc4f0e047482a..da57aad2f84fbd238ee9ba78b08c6b0d3835562e 100644 (file)
@@ -438,7 +438,7 @@ dis_compound_stmt_str = """\
               LOAD_SMALL_INT           1
               BINARY_OP               13 (+=)
               STORE_NAME               0 (x)
-              JUMP_BACKWARD            8 (to L1)
+              JUMP_BACKWARD           12 (to L1)
 """
 
 dis_traceback = """\
@@ -843,7 +843,7 @@ Disassembly of <code object <genexpr> at 0x..., file "%s", line %d>:
        L1:     RESUME                   0
                LOAD_FAST                0 (.0)
                GET_ITER
-       L2:     FOR_ITER                10 (to L3)
+       L2:     FOR_ITER                14 (to L3)
                STORE_FAST               1 (z)
                LOAD_DEREF               2 (x)
                LOAD_FAST                1 (z)
@@ -851,7 +851,7 @@ Disassembly of <code object <genexpr> at 0x..., file "%s", line %d>:
                YIELD_VALUE              0
                RESUME                   5
                POP_TOP
-               JUMP_BACKWARD           12 (to L2)
+               JUMP_BACKWARD           16 (to L2)
        L3:     END_FOR
                POP_ITER
                LOAD_CONST               0 (None)
@@ -1807,7 +1807,7 @@ expected_opinfo_jumpy = [
   Instruction(opname='POP_TOP', opcode=31, arg=None, argval=None, argrepr='', offset=116, start_offset=116, starts_line=False, line_number=10, label=None, positions=None, cache_info=None),
   Instruction(opname='LOAD_FAST_CHECK', opcode=85, arg=0, argval='i', argrepr='i', offset=118, start_offset=118, starts_line=True, line_number=11, label=5, positions=None, cache_info=None),
   Instruction(opname='TO_BOOL', opcode=39, arg=None, argval=None, argrepr='', offset=120, start_offset=120, 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=97, arg=36, argval=204, argrepr='to L8', offset=128, start_offset=128, starts_line=False, line_number=11, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]),
+  Instruction(opname='POP_JUMP_IF_FALSE', opcode=97, arg=40, argval=212, argrepr='to L8', offset=128, start_offset=128, 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=132, start_offset=132, starts_line=False, line_number=11, label=None, positions=None, cache_info=None),
   Instruction(opname='LOAD_GLOBAL', opcode=89, arg=3, argval='print', argrepr='print + NULL', offset=134, start_offset=134, 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=83, arg=0, argval='i', argrepr='i', offset=144, start_offset=144, starts_line=False, line_number=12, label=None, positions=None, cache_info=None),
@@ -1815,93 +1815,93 @@ expected_opinfo_jumpy = [
   Instruction(opname='POP_TOP', opcode=31, arg=None, argval=None, argrepr='', offset=154, start_offset=154, starts_line=False, line_number=12, label=None, positions=None, cache_info=None),
   Instruction(opname='LOAD_FAST', opcode=83, arg=0, argval='i', argrepr='i', offset=156, start_offset=156, starts_line=True, line_number=13, label=None, positions=None, cache_info=None),
   Instruction(opname='LOAD_SMALL_INT', opcode=91, arg=1, argval=1, argrepr='', offset=158, start_offset=158, starts_line=False, line_number=13, label=None, positions=None, cache_info=None),
-  Instruction(opname='BINARY_OP', opcode=44, arg=23, argval=23, argrepr='-=', offset=160, start_offset=160, starts_line=False, line_number=13, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]),
-  Instruction(opname='STORE_FAST', opcode=109, arg=0, argval='i', argrepr='i', offset=164, start_offset=164, starts_line=False, line_number=13, label=None, positions=None, cache_info=None),
-  Instruction(opname='LOAD_FAST', opcode=83, arg=0, argval='i', argrepr='i', offset=166, start_offset=166, starts_line=True, line_number=14, label=None, positions=None, cache_info=None),
-  Instruction(opname='LOAD_SMALL_INT', opcode=91, arg=6, argval=6, argrepr='', offset=168, start_offset=168, starts_line=False, line_number=14, label=None, positions=None, cache_info=None),
-  Instruction(opname='COMPARE_OP', opcode=56, arg=148, argval='>', argrepr='bool(>)', offset=170, start_offset=170, starts_line=False, line_number=14, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]),
-  Instruction(opname='POP_JUMP_IF_FALSE', opcode=97, arg=3, argval=184, argrepr='to L6', offset=174, start_offset=174, 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=178, start_offset=178, starts_line=False, line_number=14, label=None, positions=None, cache_info=None),
-  Instruction(opname='JUMP_BACKWARD', opcode=74, arg=33, argval=118, argrepr='to L5', offset=180, start_offset=180, starts_line=True, line_number=15, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]),
-  Instruction(opname='LOAD_FAST', opcode=83, arg=0, argval='i', argrepr='i', offset=184, start_offset=184, starts_line=True, line_number=16, label=6, positions=None, cache_info=None),
-  Instruction(opname='LOAD_SMALL_INT', opcode=91, arg=4, argval=4, argrepr='', offset=186, start_offset=186, starts_line=False, line_number=16, label=None, positions=None, cache_info=None),
-  Instruction(opname='COMPARE_OP', opcode=56, arg=18, argval='<', argrepr='bool(<)', offset=188, start_offset=188, starts_line=False, line_number=16, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]),
-  Instruction(opname='POP_JUMP_IF_TRUE', opcode=100, arg=3, argval=202, argrepr='to L7', offset=192, start_offset=192, 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=196, start_offset=196, starts_line=False, line_number=16, label=None, positions=None, cache_info=None),
-  Instruction(opname='JUMP_BACKWARD', opcode=74, arg=42, argval=118, argrepr='to L5', offset=198, start_offset=198, starts_line=False, line_number=16, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]),
-  Instruction(opname='JUMP_FORWARD', opcode=76, arg=11, argval=226, argrepr='to L9', offset=202, start_offset=202, starts_line=True, line_number=17, label=7, positions=None, cache_info=None),
-  Instruction(opname='LOAD_GLOBAL', opcode=89, arg=3, argval='print', argrepr='print + NULL', offset=204, start_offset=204, 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=81, arg=1, argval='Who let lolcatz into this test suite?', argrepr="'Who let lolcatz into this test suite?'", offset=214, start_offset=214, starts_line=False, line_number=19, label=None, positions=None, cache_info=None),
-  Instruction(opname='CALL', opcode=51, arg=1, argval=1, argrepr='', offset=216, start_offset=216, 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=31, arg=None, argval=None, argrepr='', offset=224, start_offset=224, starts_line=False, line_number=19, label=None, positions=None, cache_info=None),
-  Instruction(opname='NOP', opcode=27, arg=None, argval=None, argrepr='', offset=226, start_offset=226, starts_line=True, line_number=20, label=9, positions=None, cache_info=None),
-  Instruction(opname='LOAD_SMALL_INT', opcode=91, arg=1, argval=1, argrepr='', offset=228, start_offset=228, starts_line=True, line_number=21, label=None, positions=None, cache_info=None),
-  Instruction(opname='LOAD_SMALL_INT', opcode=91, arg=0, argval=0, argrepr='', offset=230, start_offset=230, starts_line=False, line_number=21, label=None, positions=None, cache_info=None),
-  Instruction(opname='BINARY_OP', opcode=44, arg=11, argval=11, argrepr='/', offset=232, start_offset=232, starts_line=False, line_number=21, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]),
-  Instruction(opname='POP_TOP', opcode=31, arg=None, argval=None, argrepr='', offset=236, start_offset=236, starts_line=False, line_number=21, label=None, positions=None, cache_info=None),
-  Instruction(opname='LOAD_FAST', opcode=83, arg=0, argval='i', argrepr='i', offset=238, start_offset=238, starts_line=True, line_number=25, label=None, positions=None, cache_info=None),
-  Instruction(opname='COPY', opcode=59, arg=1, argval=1, argrepr='', offset=240, start_offset=240, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
-  Instruction(opname='LOAD_SPECIAL', opcode=92, arg=1, argval=1, argrepr='__exit__', offset=242, start_offset=242, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
-  Instruction(opname='SWAP', opcode=114, arg=2, argval=2, argrepr='', offset=244, start_offset=244, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
-  Instruction(opname='SWAP', opcode=114, arg=3, argval=3, argrepr='', offset=246, start_offset=246, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
-  Instruction(opname='LOAD_SPECIAL', opcode=92, arg=0, argval=0, argrepr='__enter__', offset=248, start_offset=248, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
-  Instruction(opname='CALL', opcode=51, arg=0, argval=0, argrepr='', offset=250, start_offset=250, 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=109, arg=1, argval='dodgy', argrepr='dodgy', offset=258, start_offset=258, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
-  Instruction(opname='LOAD_GLOBAL', opcode=89, arg=3, argval='print', argrepr='print + NULL', offset=260, start_offset=260, 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=81, arg=2, argval='Never reach this', argrepr="'Never reach this'", offset=270, start_offset=270, starts_line=False, line_number=26, label=None, positions=None, cache_info=None),
-  Instruction(opname='CALL', opcode=51, arg=1, argval=1, argrepr='', offset=272, start_offset=272, 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=31, arg=None, argval=None, argrepr='', offset=280, start_offset=280, starts_line=False, line_number=26, label=None, positions=None, cache_info=None),
-  Instruction(opname='LOAD_CONST', opcode=81, arg=3, argval=None, argrepr='None', offset=282, start_offset=282, starts_line=True, line_number=25, label=None, positions=None, cache_info=None),
-  Instruction(opname='LOAD_CONST', opcode=81, arg=3, argval=None, argrepr='None', offset=284, start_offset=284, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
-  Instruction(opname='LOAD_CONST', opcode=81, arg=3, argval=None, argrepr='None', offset=286, start_offset=286, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
-  Instruction(opname='CALL', opcode=51, arg=3, argval=3, argrepr='', offset=288, start_offset=288, 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=31, arg=None, argval=None, argrepr='', offset=296, start_offset=296, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
-  Instruction(opname='LOAD_GLOBAL', opcode=89, arg=3, argval='print', argrepr='print + NULL', offset=298, start_offset=298, 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=81, arg=5, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=308, start_offset=308, starts_line=False, line_number=28, label=None, positions=None, cache_info=None),
-  Instruction(opname='CALL', opcode=51, arg=1, argval=1, argrepr='', offset=310, start_offset=310, 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=31, arg=None, argval=None, argrepr='', offset=318, start_offset=318, starts_line=False, line_number=28, label=None, positions=None, cache_info=None),
-  Instruction(opname='LOAD_CONST', opcode=81, arg=3, argval=None, argrepr='None', offset=320, start_offset=320, starts_line=False, line_number=28, label=None, positions=None, cache_info=None),
-  Instruction(opname='RETURN_VALUE', opcode=35, arg=None, argval=None, argrepr='', offset=322, start_offset=322, starts_line=False, line_number=28, label=None, positions=None, cache_info=None),
-  Instruction(opname='PUSH_EXC_INFO', opcode=32, arg=None, argval=None, argrepr='', offset=324, start_offset=324, starts_line=True, line_number=25, label=None, positions=None, cache_info=None),
-  Instruction(opname='WITH_EXCEPT_START', opcode=43, arg=None, argval=None, argrepr='', offset=326, start_offset=326, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
-  Instruction(opname='TO_BOOL', opcode=39, arg=None, argval=None, argrepr='', offset=328, start_offset=328, 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=100, arg=2, argval=344, argrepr='to L11', offset=336, start_offset=336, 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=340, start_offset=340, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
-  Instruction(opname='RERAISE', opcode=102, arg=2, argval=2, argrepr='', offset=342, start_offset=342, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
-  Instruction(opname='POP_TOP', opcode=31, arg=None, argval=None, argrepr='', offset=344, start_offset=344, 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=346, start_offset=346, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
-  Instruction(opname='POP_TOP', opcode=31, arg=None, argval=None, argrepr='', offset=348, start_offset=348, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
-  Instruction(opname='POP_TOP', opcode=31, arg=None, argval=None, argrepr='', offset=350, start_offset=350, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
-  Instruction(opname='POP_TOP', opcode=31, 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='JUMP_BACKWARD_NO_INTERRUPT', opcode=75, arg=29, argval=298, argrepr='to L10', offset=354, start_offset=354, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
-  Instruction(opname='COPY', opcode=59, arg=3, argval=3, argrepr='', offset=356, start_offset=356, 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=358, start_offset=358, starts_line=False, line_number=None, label=None, positions=None, cache_info=None),
-  Instruction(opname='RERAISE', opcode=102, arg=1, argval=1, argrepr='', offset=360, start_offset=360, starts_line=False, line_number=None, label=None, positions=None, cache_info=None),
-  Instruction(opname='PUSH_EXC_INFO', opcode=32, arg=None, argval=None, argrepr='', offset=362, start_offset=362, starts_line=False, line_number=None, label=None, positions=None, cache_info=None),
-  Instruction(opname='LOAD_GLOBAL', opcode=89, arg=4, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=364, start_offset=364, 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=374, start_offset=374, starts_line=False, line_number=22, label=None, positions=None, cache_info=None),
-  Instruction(opname='POP_JUMP_IF_FALSE', opcode=97, arg=15, argval=410, argrepr='to L12', offset=376, start_offset=376, 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=380, start_offset=380, starts_line=False, line_number=22, label=None, positions=None, cache_info=None),
-  Instruction(opname='POP_TOP', opcode=31, arg=None, argval=None, argrepr='', offset=382, start_offset=382, starts_line=False, line_number=22, label=None, positions=None, cache_info=None),
-  Instruction(opname='LOAD_GLOBAL', opcode=89, arg=3, argval='print', argrepr='print + NULL', offset=384, start_offset=384, 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=81, arg=4, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=394, start_offset=394, starts_line=False, line_number=23, label=None, positions=None, cache_info=None),
-  Instruction(opname='CALL', opcode=51, arg=1, argval=1, argrepr='', offset=396, start_offset=396, 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=31, arg=None, argval=None, argrepr='', offset=404, start_offset=404, 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=406, start_offset=406, starts_line=False, line_number=23, label=None, positions=None, cache_info=None),
-  Instruction(opname='JUMP_BACKWARD_NO_INTERRUPT', opcode=75, arg=56, argval=298, argrepr='to L10', offset=408, start_offset=408, starts_line=False, line_number=23, label=None, positions=None, cache_info=None),
-  Instruction(opname='RERAISE', opcode=102, arg=0, argval=0, argrepr='', offset=410, start_offset=410, starts_line=True, line_number=22, label=12, positions=None, cache_info=None),
-  Instruction(opname='COPY', opcode=59, arg=3, argval=3, argrepr='', offset=412, start_offset=412, 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=414, start_offset=414, starts_line=False, line_number=None, label=None, positions=None, cache_info=None),
-  Instruction(opname='RERAISE', opcode=102, arg=1, argval=1, argrepr='', offset=416, start_offset=416, starts_line=False, line_number=None, label=None, positions=None, cache_info=None),
-  Instruction(opname='PUSH_EXC_INFO', opcode=32, arg=None, argval=None, argrepr='', offset=418, start_offset=418, starts_line=False, line_number=None, label=None, positions=None, cache_info=None),
-  Instruction(opname='LOAD_GLOBAL', opcode=89, arg=3, argval='print', argrepr='print + NULL', offset=420, start_offset=420, 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=81, arg=5, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=430, start_offset=430, starts_line=False, line_number=28, label=None, positions=None, cache_info=None),
-  Instruction(opname='CALL', opcode=51, arg=1, argval=1, argrepr='', offset=432, start_offset=432, 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=31, arg=None, argval=None, argrepr='', offset=440, start_offset=440, starts_line=False, line_number=28, label=None, positions=None, cache_info=None),
-  Instruction(opname='RERAISE', opcode=102, arg=0, argval=0, argrepr='', offset=442, start_offset=442, starts_line=False, line_number=28, label=None, positions=None, cache_info=None),
-  Instruction(opname='COPY', opcode=59, arg=3, argval=3, argrepr='', offset=444, start_offset=444, 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=446, start_offset=446, starts_line=False, line_number=None, label=None, positions=None, cache_info=None),
-  Instruction(opname='RERAISE', opcode=102, arg=1, argval=1, argrepr='', offset=448, start_offset=448, starts_line=False, line_number=None, label=None, positions=None, cache_info=None),
+  Instruction(opname='BINARY_OP', opcode=44, arg=23, argval=23, argrepr='-=', offset=160, start_offset=160, starts_line=False, line_number=13, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('descr', 4, b'\x00\x00\x00\x00\x00\x00\x00\x00')]),
+  Instruction(opname='STORE_FAST', opcode=109, arg=0, argval='i', argrepr='i', offset=172, start_offset=172, starts_line=False, line_number=13, label=None, positions=None, cache_info=None),
+  Instruction(opname='LOAD_FAST', opcode=83, arg=0, argval='i', argrepr='i', offset=174, start_offset=174, starts_line=True, line_number=14, label=None, positions=None, cache_info=None),
+  Instruction(opname='LOAD_SMALL_INT', opcode=91, arg=6, argval=6, argrepr='', offset=176, start_offset=176, starts_line=False, line_number=14, label=None, positions=None, cache_info=None),
+  Instruction(opname='COMPARE_OP', opcode=56, arg=148, argval='>', argrepr='bool(>)', offset=178, start_offset=178, starts_line=False, line_number=14, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]),
+  Instruction(opname='POP_JUMP_IF_FALSE', opcode=97, arg=3, argval=192, argrepr='to L6', offset=182, start_offset=182, 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=186, start_offset=186, starts_line=False, line_number=14, label=None, positions=None, cache_info=None),
+  Instruction(opname='JUMP_BACKWARD', opcode=74, arg=37, argval=118, argrepr='to L5', offset=188, start_offset=188, starts_line=True, line_number=15, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]),
+  Instruction(opname='LOAD_FAST', opcode=83, arg=0, argval='i', argrepr='i', offset=192, start_offset=192, starts_line=True, line_number=16, label=6, positions=None, cache_info=None),
+  Instruction(opname='LOAD_SMALL_INT', opcode=91, arg=4, argval=4, argrepr='', offset=194, start_offset=194, starts_line=False, line_number=16, label=None, positions=None, cache_info=None),
+  Instruction(opname='COMPARE_OP', opcode=56, arg=18, argval='<', argrepr='bool(<)', offset=196, start_offset=196, starts_line=False, line_number=16, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]),
+  Instruction(opname='POP_JUMP_IF_TRUE', opcode=100, arg=3, argval=210, argrepr='to L7', offset=200, start_offset=200, 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=204, start_offset=204, starts_line=False, line_number=16, label=None, positions=None, cache_info=None),
+  Instruction(opname='JUMP_BACKWARD', opcode=74, arg=46, argval=118, argrepr='to L5', offset=206, start_offset=206, starts_line=False, line_number=16, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00')]),
+  Instruction(opname='JUMP_FORWARD', opcode=76, arg=11, argval=234, argrepr='to L9', offset=210, start_offset=210, starts_line=True, line_number=17, label=7, positions=None, cache_info=None),
+  Instruction(opname='LOAD_GLOBAL', opcode=89, arg=3, argval='print', argrepr='print + NULL', offset=212, start_offset=212, 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=81, arg=1, argval='Who let lolcatz into this test suite?', argrepr="'Who let lolcatz into this test suite?'", offset=222, start_offset=222, starts_line=False, line_number=19, label=None, positions=None, cache_info=None),
+  Instruction(opname='CALL', opcode=51, arg=1, argval=1, argrepr='', offset=224, start_offset=224, 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=31, arg=None, argval=None, argrepr='', offset=232, start_offset=232, starts_line=False, line_number=19, label=None, positions=None, cache_info=None),
+  Instruction(opname='NOP', opcode=27, arg=None, argval=None, argrepr='', offset=234, start_offset=234, starts_line=True, line_number=20, label=9, positions=None, cache_info=None),
+  Instruction(opname='LOAD_SMALL_INT', opcode=91, arg=1, argval=1, argrepr='', offset=236, start_offset=236, starts_line=True, line_number=21, label=None, positions=None, cache_info=None),
+  Instruction(opname='LOAD_SMALL_INT', opcode=91, arg=0, argval=0, argrepr='', offset=238, start_offset=238, starts_line=False, line_number=21, label=None, positions=None, cache_info=None),
+  Instruction(opname='BINARY_OP', opcode=44, arg=11, argval=11, argrepr='/', offset=240, start_offset=240, starts_line=False, line_number=21, label=None, positions=None, cache_info=[('counter', 1, b'\x00\x00'), ('descr', 4, b'\x00\x00\x00\x00\x00\x00\x00\x00')]),
+  Instruction(opname='POP_TOP', opcode=31, arg=None, argval=None, argrepr='', offset=252, start_offset=252, starts_line=False, line_number=21, label=None, positions=None, cache_info=None),
+  Instruction(opname='LOAD_FAST', opcode=83, arg=0, argval='i', argrepr='i', offset=254, start_offset=254, starts_line=True, line_number=25, label=None, positions=None, cache_info=None),
+  Instruction(opname='COPY', opcode=59, arg=1, argval=1, argrepr='', offset=256, start_offset=256, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
+  Instruction(opname='LOAD_SPECIAL', opcode=92, arg=1, argval=1, argrepr='__exit__', offset=258, start_offset=258, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
+  Instruction(opname='SWAP', opcode=114, arg=2, argval=2, argrepr='', offset=260, start_offset=260, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
+  Instruction(opname='SWAP', opcode=114, arg=3, argval=3, argrepr='', offset=262, start_offset=262, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
+  Instruction(opname='LOAD_SPECIAL', opcode=92, arg=0, argval=0, argrepr='__enter__', offset=264, start_offset=264, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
+  Instruction(opname='CALL', opcode=51, arg=0, argval=0, argrepr='', offset=266, start_offset=266, 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=109, arg=1, argval='dodgy', argrepr='dodgy', offset=274, start_offset=274, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
+  Instruction(opname='LOAD_GLOBAL', opcode=89, arg=3, argval='print', argrepr='print + NULL', offset=276, start_offset=276, 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=81, arg=2, argval='Never reach this', argrepr="'Never reach this'", offset=286, start_offset=286, starts_line=False, line_number=26, label=None, positions=None, cache_info=None),
+  Instruction(opname='CALL', opcode=51, arg=1, argval=1, argrepr='', offset=288, start_offset=288, 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=31, arg=None, argval=None, argrepr='', offset=296, start_offset=296, starts_line=False, line_number=26, label=None, positions=None, cache_info=None),
+  Instruction(opname='LOAD_CONST', opcode=81, arg=3, argval=None, argrepr='None', offset=298, start_offset=298, starts_line=True, line_number=25, label=None, positions=None, cache_info=None),
+  Instruction(opname='LOAD_CONST', opcode=81, arg=3, argval=None, argrepr='None', offset=300, start_offset=300, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
+  Instruction(opname='LOAD_CONST', opcode=81, arg=3, argval=None, argrepr='None', offset=302, start_offset=302, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
+  Instruction(opname='CALL', opcode=51, arg=3, argval=3, argrepr='', offset=304, start_offset=304, 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=31, arg=None, argval=None, argrepr='', offset=312, start_offset=312, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
+  Instruction(opname='LOAD_GLOBAL', opcode=89, arg=3, argval='print', argrepr='print + NULL', offset=314, start_offset=314, 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=81, arg=5, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=324, start_offset=324, starts_line=False, line_number=28, label=None, positions=None, cache_info=None),
+  Instruction(opname='CALL', opcode=51, arg=1, argval=1, argrepr='', offset=326, start_offset=326, 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=31, arg=None, argval=None, argrepr='', offset=334, start_offset=334, starts_line=False, line_number=28, label=None, positions=None, cache_info=None),
+  Instruction(opname='LOAD_CONST', opcode=81, arg=3, argval=None, argrepr='None', offset=336, start_offset=336, starts_line=False, line_number=28, label=None, positions=None, cache_info=None),
+  Instruction(opname='RETURN_VALUE', opcode=35, arg=None, argval=None, argrepr='', offset=338, start_offset=338, starts_line=False, line_number=28, label=None, positions=None, cache_info=None),
+  Instruction(opname='PUSH_EXC_INFO', opcode=32, arg=None, argval=None, argrepr='', offset=340, start_offset=340, starts_line=True, line_number=25, label=None, positions=None, cache_info=None),
+  Instruction(opname='WITH_EXCEPT_START', opcode=43, arg=None, argval=None, argrepr='', offset=342, start_offset=342, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
+  Instruction(opname='TO_BOOL', opcode=39, arg=None, argval=None, argrepr='', offset=344, start_offset=344, 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=100, arg=2, argval=360, argrepr='to L11', offset=352, start_offset=352, 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=356, start_offset=356, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
+  Instruction(opname='RERAISE', opcode=102, arg=2, argval=2, argrepr='', offset=358, start_offset=358, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
+  Instruction(opname='POP_TOP', opcode=31, arg=None, argval=None, argrepr='', offset=360, start_offset=360, 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=362, start_offset=362, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
+  Instruction(opname='POP_TOP', opcode=31, arg=None, argval=None, argrepr='', offset=364, start_offset=364, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
+  Instruction(opname='POP_TOP', opcode=31, arg=None, argval=None, argrepr='', offset=366, start_offset=366, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
+  Instruction(opname='POP_TOP', opcode=31, arg=None, argval=None, argrepr='', offset=368, start_offset=368, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
+  Instruction(opname='JUMP_BACKWARD_NO_INTERRUPT', opcode=75, arg=29, argval=314, argrepr='to L10', offset=370, start_offset=370, starts_line=False, line_number=25, label=None, positions=None, cache_info=None),
+  Instruction(opname='COPY', opcode=59, arg=3, argval=3, argrepr='', offset=372, start_offset=372, 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=374, start_offset=374, starts_line=False, line_number=None, label=None, positions=None, cache_info=None),
+  Instruction(opname='RERAISE', opcode=102, arg=1, argval=1, argrepr='', offset=376, start_offset=376, starts_line=False, line_number=None, label=None, positions=None, cache_info=None),
+  Instruction(opname='PUSH_EXC_INFO', opcode=32, arg=None, argval=None, argrepr='', offset=378, start_offset=378, starts_line=False, line_number=None, label=None, positions=None, cache_info=None),
+  Instruction(opname='LOAD_GLOBAL', opcode=89, arg=4, argval='ZeroDivisionError', argrepr='ZeroDivisionError', offset=380, start_offset=380, 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=390, start_offset=390, starts_line=False, line_number=22, label=None, positions=None, cache_info=None),
+  Instruction(opname='POP_JUMP_IF_FALSE', opcode=97, arg=15, argval=426, argrepr='to L12', offset=392, start_offset=392, 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=396, start_offset=396, starts_line=False, line_number=22, label=None, positions=None, cache_info=None),
+  Instruction(opname='POP_TOP', opcode=31, arg=None, argval=None, argrepr='', offset=398, start_offset=398, starts_line=False, line_number=22, label=None, positions=None, cache_info=None),
+  Instruction(opname='LOAD_GLOBAL', opcode=89, arg=3, argval='print', argrepr='print + NULL', offset=400, start_offset=400, 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=81, arg=4, argval='Here we go, here we go, here we go...', argrepr="'Here we go, here we go, here we go...'", offset=410, start_offset=410, starts_line=False, line_number=23, label=None, positions=None, cache_info=None),
+  Instruction(opname='CALL', opcode=51, arg=1, argval=1, argrepr='', offset=412, start_offset=412, 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=31, arg=None, argval=None, argrepr='', offset=420, start_offset=420, 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=422, start_offset=422, starts_line=False, line_number=23, label=None, positions=None, cache_info=None),
+  Instruction(opname='JUMP_BACKWARD_NO_INTERRUPT', opcode=75, arg=56, argval=314, argrepr='to L10', offset=424, start_offset=424, starts_line=False, line_number=23, label=None, positions=None, cache_info=None),
+  Instruction(opname='RERAISE', opcode=102, arg=0, argval=0, argrepr='', offset=426, start_offset=426, starts_line=True, line_number=22, label=12, positions=None, cache_info=None),
+  Instruction(opname='COPY', opcode=59, arg=3, argval=3, argrepr='', offset=428, start_offset=428, 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=430, start_offset=430, starts_line=False, line_number=None, label=None, positions=None, cache_info=None),
+  Instruction(opname='RERAISE', opcode=102, arg=1, argval=1, argrepr='', offset=432, start_offset=432, starts_line=False, line_number=None, label=None, positions=None, cache_info=None),
+  Instruction(opname='PUSH_EXC_INFO', opcode=32, arg=None, argval=None, argrepr='', offset=434, start_offset=434, starts_line=False, line_number=None, label=None, positions=None, cache_info=None),
+  Instruction(opname='LOAD_GLOBAL', opcode=89, arg=3, argval='print', argrepr='print + NULL', offset=436, start_offset=436, 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=81, arg=5, argval="OK, now we're done", argrepr='"OK, now we\'re done"', offset=446, start_offset=446, starts_line=False, line_number=28, label=None, positions=None, cache_info=None),
+  Instruction(opname='CALL', opcode=51, arg=1, argval=1, argrepr='', offset=448, start_offset=448, 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=31, arg=None, argval=None, argrepr='', offset=456, start_offset=456, starts_line=False, line_number=28, label=None, positions=None, cache_info=None),
+  Instruction(opname='RERAISE', opcode=102, arg=0, argval=0, argrepr='', offset=458, start_offset=458, starts_line=False, line_number=28, label=None, positions=None, cache_info=None),
+  Instruction(opname='COPY', opcode=59, arg=3, argval=3, argrepr='', offset=460, start_offset=460, 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=462, start_offset=462, starts_line=False, line_number=None, label=None, positions=None, cache_info=None),
+  Instruction(opname='RERAISE', opcode=102, arg=1, argval=1, argrepr='', offset=464, start_offset=464, 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
index 43e3e56639db6284a483139b004b2a4d755795ba..bea0e48883bf9a52d822a42000ab6374665b24af 100644 (file)
@@ -1649,7 +1649,7 @@ class TestBranchAndJumpEvents(CheckEvents):
             return None
 
         in_loop = ('branch left', 'foo', 10, 16)
-        exit_loop = ('branch right', 'foo', 10, 32)
+        exit_loop = ('branch right', 'foo', 10, 40)
         self.check_events(foo, recorders = BRANCH_OFFSET_RECORDERS, expected = [
             in_loop,
             in_loop,
index b80ccbf17f1ee6009a4b82becb160e871dc7ec51..72b845fcc8fdbf92f80961970e8df6a013f6d0a9 100644 (file)
@@ -1338,6 +1338,31 @@ class TestSpecializer(TestBase):
         self.assert_specialized(binary_op_add_unicode, "BINARY_OP_ADD_UNICODE")
         self.assert_no_opcode(binary_op_add_unicode, "BINARY_OP")
 
+        def binary_op_add_extend():
+            for _ in range(100):
+                a, b = 6, 3.0
+                c = a + b
+                self.assertEqual(c, 9.0)
+                c = b + a
+                self.assertEqual(c, 9.0)
+                c = a - b
+                self.assertEqual(c, 3.0)
+                c = b - a
+                self.assertEqual(c, -3.0)
+                c = a * b
+                self.assertEqual(c, 18.0)
+                c = b * a
+                self.assertEqual(c, 18.0)
+                c = a / b
+                self.assertEqual(c, 2.0)
+                c = b / a
+                self.assertEqual(c, 0.5)
+
+        binary_op_add_extend()
+        self.assert_specialized(binary_op_add_extend, "BINARY_OP_EXTEND")
+        self.assert_no_opcode(binary_op_add_extend, "BINARY_OP")
+
+
     @cpython_only
     @requires_specialization_ft
     def test_load_super_attr(self):
diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-01-10-23-54-16.gh-issue-100239.ijOOUs.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-01-10-23-54-16.gh-issue-100239.ijOOUs.rst
new file mode 100644 (file)
index 0000000..f58c1fc
--- /dev/null
@@ -0,0 +1,2 @@
+Add opcode ``BINARY_OP_EXTEND`` which executes a pair of functions (guard and
+specialization functions) accessed from the inline cache.
index a906ded365650c981cf9cae5df656640c799815f..b1d61a8707bd4cb0d53d5820186d1498a50d38e9 100644 (file)
@@ -522,6 +522,7 @@ dummy_func(
             BINARY_OP_SUBTRACT_FLOAT,
             BINARY_OP_ADD_UNICODE,
             // BINARY_OP_INPLACE_ADD_UNICODE,  // See comments at that opcode.
+            BINARY_OP_EXTEND,
         };
 
         op(_GUARD_BOTH_INT, (left, right -- left, right)) {
@@ -587,11 +588,11 @@ dummy_func(
         }
 
         macro(BINARY_OP_MULTIPLY_INT) =
-            _GUARD_BOTH_INT + unused/1 + _BINARY_OP_MULTIPLY_INT;
+            _GUARD_BOTH_INT + unused/5 + _BINARY_OP_MULTIPLY_INT;
         macro(BINARY_OP_ADD_INT) =
-            _GUARD_BOTH_INT + unused/1 + _BINARY_OP_ADD_INT;
+            _GUARD_BOTH_INT + unused/5 + _BINARY_OP_ADD_INT;
         macro(BINARY_OP_SUBTRACT_INT) =
-            _GUARD_BOTH_INT + unused/1 + _BINARY_OP_SUBTRACT_INT;
+            _GUARD_BOTH_INT + unused/5 + _BINARY_OP_SUBTRACT_INT;
 
         op(_GUARD_BOTH_FLOAT, (left, right -- left, right)) {
             PyObject *left_o = PyStackRef_AsPyObjectBorrow(left);
@@ -659,11 +660,11 @@ dummy_func(
         }
 
         macro(BINARY_OP_MULTIPLY_FLOAT) =
-            _GUARD_BOTH_FLOAT + unused/1 + _BINARY_OP_MULTIPLY_FLOAT;
+            _GUARD_BOTH_FLOAT + unused/5 + _BINARY_OP_MULTIPLY_FLOAT;
         macro(BINARY_OP_ADD_FLOAT) =
-            _GUARD_BOTH_FLOAT + unused/1 + _BINARY_OP_ADD_FLOAT;
+            _GUARD_BOTH_FLOAT + unused/5 + _BINARY_OP_ADD_FLOAT;
         macro(BINARY_OP_SUBTRACT_FLOAT) =
-            _GUARD_BOTH_FLOAT + unused/1 + _BINARY_OP_SUBTRACT_FLOAT;
+            _GUARD_BOTH_FLOAT + unused/5 + _BINARY_OP_SUBTRACT_FLOAT;
 
         op(_GUARD_BOTH_UNICODE, (left, right -- left, right)) {
             PyObject *left_o = PyStackRef_AsPyObjectBorrow(left);
@@ -689,7 +690,7 @@ dummy_func(
         }
 
         macro(BINARY_OP_ADD_UNICODE) =
-            _GUARD_BOTH_UNICODE + unused/1 + _BINARY_OP_ADD_UNICODE;
+            _GUARD_BOTH_UNICODE + unused/5 + _BINARY_OP_ADD_UNICODE;
 
         // This is a subtle one. It's a super-instruction for
         // BINARY_OP_ADD_UNICODE followed by STORE_FAST
@@ -741,8 +742,34 @@ dummy_func(
         #endif
         }
 
+       op(_GUARD_BINARY_OP_EXTEND, (descr/4, left, right -- left, right)) {
+            PyObject *left_o = PyStackRef_AsPyObjectBorrow(left);
+            PyObject *right_o = PyStackRef_AsPyObjectBorrow(right);
+            _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr*)descr;
+            assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5);
+            assert(d && d->guard);
+            int res = d->guard(left_o, right_o);
+            EXIT_IF(!res);
+        }
+
+        pure op(_BINARY_OP_EXTEND, (descr/4, left, right -- res)) {
+            PyObject *left_o = PyStackRef_AsPyObjectBorrow(left);
+            PyObject *right_o = PyStackRef_AsPyObjectBorrow(right);
+            assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5);
+            _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr*)descr;
+
+            STAT_INC(BINARY_OP, hit);
+
+            PyObject *res_o = d->action(left_o, right_o);
+            DECREF_INPUTS();
+            res = PyStackRef_FromPyObjectSteal(res_o);
+        }
+
+        macro(BINARY_OP_EXTEND) =
+            unused/1 + _GUARD_BINARY_OP_EXTEND + rewind/-4 + _BINARY_OP_EXTEND;
+
         macro(BINARY_OP_INPLACE_ADD_UNICODE) =
-            _GUARD_BOTH_UNICODE + unused/1 + _BINARY_OP_INPLACE_ADD_UNICODE;
+            _GUARD_BOTH_UNICODE + unused/5 + _BINARY_OP_INPLACE_ADD_UNICODE;
 
         family(BINARY_SUBSCR, INLINE_CACHE_ENTRIES_BINARY_SUBSCR) = {
             BINARY_SUBSCR_DICT,
@@ -4742,7 +4769,7 @@ dummy_func(
             res = PyStackRef_FromPyObjectSteal(res_o);
         }
 
-        macro(BINARY_OP) = _SPECIALIZE_BINARY_OP + _BINARY_OP;
+        macro(BINARY_OP) = _SPECIALIZE_BINARY_OP + unused/4 + _BINARY_OP;
 
         pure inst(SWAP, (bottom_in, unused[oparg-2], top_in --
                     top_out, unused[oparg-2], bottom_out)) {
index cda01bb768c2699fb494a593a66afa39562247ea..ad825881c8228c8e337b9b4370c19a84272273d3 100644 (file)
             break;
         }
 
+        case _GUARD_BINARY_OP_EXTEND: {
+            _PyStackRef right;
+            _PyStackRef left;
+            right = stack_pointer[-1];
+            left = stack_pointer[-2];
+            PyObject *descr = (PyObject *)CURRENT_OPERAND0();
+            PyObject *left_o = PyStackRef_AsPyObjectBorrow(left);
+            PyObject *right_o = PyStackRef_AsPyObjectBorrow(right);
+            _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr*)descr;
+            assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5);
+            assert(d && d->guard);
+            _PyFrame_SetStackPointer(frame, stack_pointer);
+            int res = d->guard(left_o, right_o);
+            stack_pointer = _PyFrame_GetStackPointer(frame);
+            if (!res) {
+                UOP_STAT_INC(uopcode, miss);
+                JUMP_TO_JUMP_TARGET();
+            }
+            break;
+        }
+
+        case _BINARY_OP_EXTEND: {
+            _PyStackRef right;
+            _PyStackRef left;
+            _PyStackRef res;
+            right = stack_pointer[-1];
+            left = stack_pointer[-2];
+            PyObject *descr = (PyObject *)CURRENT_OPERAND0();
+            PyObject *left_o = PyStackRef_AsPyObjectBorrow(left);
+            PyObject *right_o = PyStackRef_AsPyObjectBorrow(right);
+            assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5);
+            _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr*)descr;
+            STAT_INC(BINARY_OP, hit);
+            _PyFrame_SetStackPointer(frame, stack_pointer);
+            PyObject *res_o = d->action(left_o, right_o);
+            stack_pointer = _PyFrame_GetStackPointer(frame);
+            PyStackRef_CLOSE(left);
+            PyStackRef_CLOSE(right);
+            res = PyStackRef_FromPyObjectSteal(res_o);
+            stack_pointer[-2] = res;
+            stack_pointer += -1;
+            assert(WITHIN_STACK_BOUNDS());
+            break;
+        }
+
         case _BINARY_SUBSCR: {
             _PyStackRef sub;
             _PyStackRef container;
index 81408380d6b2b8e00bac57a7aaf012b6126361a7..dc90f75f2645e1a71eeb741fcb90baf1b34ab1dd 100644 (file)
 
         TARGET(BINARY_OP) {
             frame->instr_ptr = next_instr;
-            next_instr += 2;
+            next_instr += 6;
             INSTRUCTION_STATS(BINARY_OP);
             PREDICTED(BINARY_OP);
-            _Py_CODEUNIT* const this_instr = next_instr - 2;
+            _Py_CODEUNIT* const this_instr = next_instr - 6;
             (void)this_instr;
             _PyStackRef lhs;
             _PyStackRef rhs;
@@ -39,6 +39,7 @@
                 assert(NB_ADD <= oparg);
                 assert(oparg <= NB_INPLACE_XOR);
             }
+            /* Skip 4 cache entries */
             // _BINARY_OP
             {
                 PyObject *lhs_o = PyStackRef_AsPyObjectBorrow(lhs);
@@ -60,9 +61,9 @@
 
         TARGET(BINARY_OP_ADD_FLOAT) {
             frame->instr_ptr = next_instr;
-            next_instr += 2;
+            next_instr += 6;
             INSTRUCTION_STATS(BINARY_OP_ADD_FLOAT);
-            static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 1, "incorrect cache size");
+            static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5, "incorrect cache size");
             _PyStackRef left;
             _PyStackRef right;
             _PyStackRef res;
@@ -75,7 +76,7 @@
                 DEOPT_IF(!PyFloat_CheckExact(left_o), BINARY_OP);
                 DEOPT_IF(!PyFloat_CheckExact(right_o), BINARY_OP);
             }
-            /* Skip 1 cache entry */
+            /* Skip 5 cache entries */
             // _BINARY_OP_ADD_FLOAT
             {
                 PyObject *left_o = PyStackRef_AsPyObjectBorrow(left);
@@ -98,9 +99,9 @@
 
         TARGET(BINARY_OP_ADD_INT) {
             frame->instr_ptr = next_instr;
-            next_instr += 2;
+            next_instr += 6;
             INSTRUCTION_STATS(BINARY_OP_ADD_INT);
-            static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 1, "incorrect cache size");
+            static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5, "incorrect cache size");
             _PyStackRef left;
             _PyStackRef right;
             _PyStackRef res;
                 DEOPT_IF(!PyLong_CheckExact(left_o), BINARY_OP);
                 DEOPT_IF(!PyLong_CheckExact(right_o), BINARY_OP);
             }
-            /* Skip 1 cache entry */
+            /* Skip 5 cache entries */
             // _BINARY_OP_ADD_INT
             {
                 PyObject *left_o = PyStackRef_AsPyObjectBorrow(left);
 
         TARGET(BINARY_OP_ADD_UNICODE) {
             frame->instr_ptr = next_instr;
-            next_instr += 2;
+            next_instr += 6;
             INSTRUCTION_STATS(BINARY_OP_ADD_UNICODE);
-            static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 1, "incorrect cache size");
+            static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5, "incorrect cache size");
             _PyStackRef left;
             _PyStackRef right;
             _PyStackRef res;
                 DEOPT_IF(!PyUnicode_CheckExact(left_o), BINARY_OP);
                 DEOPT_IF(!PyUnicode_CheckExact(right_o), BINARY_OP);
             }
-            /* Skip 1 cache entry */
+            /* Skip 5 cache entries */
             // _BINARY_OP_ADD_UNICODE
             {
                 PyObject *left_o = PyStackRef_AsPyObjectBorrow(left);
             DISPATCH();
         }
 
+        TARGET(BINARY_OP_EXTEND) {
+            _Py_CODEUNIT* const this_instr = frame->instr_ptr = next_instr;
+            next_instr += 6;
+            INSTRUCTION_STATS(BINARY_OP_EXTEND);
+            static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5, "incorrect cache size");
+            _PyStackRef left;
+            _PyStackRef right;
+            _PyStackRef res;
+            /* Skip 1 cache entry */
+            // _GUARD_BINARY_OP_EXTEND
+            {
+                right = stack_pointer[-1];
+                left = stack_pointer[-2];
+                PyObject *descr = read_obj(&this_instr[2].cache);
+                PyObject *left_o = PyStackRef_AsPyObjectBorrow(left);
+                PyObject *right_o = PyStackRef_AsPyObjectBorrow(right);
+                _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr*)descr;
+                assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5);
+                assert(d && d->guard);
+                _PyFrame_SetStackPointer(frame, stack_pointer);
+                int res = d->guard(left_o, right_o);
+                stack_pointer = _PyFrame_GetStackPointer(frame);
+                DEOPT_IF(!res, BINARY_OP);
+            }
+            /* Skip -4 cache entry */
+            // _BINARY_OP_EXTEND
+            {
+                PyObject *descr = read_obj(&this_instr[2].cache);
+                PyObject *left_o = PyStackRef_AsPyObjectBorrow(left);
+                PyObject *right_o = PyStackRef_AsPyObjectBorrow(right);
+                assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5);
+                _PyBinaryOpSpecializationDescr *d = (_PyBinaryOpSpecializationDescr*)descr;
+                STAT_INC(BINARY_OP, hit);
+                _PyFrame_SetStackPointer(frame, stack_pointer);
+                PyObject *res_o = d->action(left_o, right_o);
+                stack_pointer = _PyFrame_GetStackPointer(frame);
+                PyStackRef_CLOSE(left);
+                PyStackRef_CLOSE(right);
+                res = PyStackRef_FromPyObjectSteal(res_o);
+            }
+            stack_pointer[-2] = res;
+            stack_pointer += -1;
+            assert(WITHIN_STACK_BOUNDS());
+            DISPATCH();
+        }
+
         TARGET(BINARY_OP_INPLACE_ADD_UNICODE) {
             frame->instr_ptr = next_instr;
-            next_instr += 2;
+            next_instr += 6;
             INSTRUCTION_STATS(BINARY_OP_INPLACE_ADD_UNICODE);
-            static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 1, "incorrect cache size");
+            static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5, "incorrect cache size");
             _PyStackRef left;
             _PyStackRef right;
             // _GUARD_BOTH_UNICODE
                 DEOPT_IF(!PyUnicode_CheckExact(left_o), BINARY_OP);
                 DEOPT_IF(!PyUnicode_CheckExact(right_o), BINARY_OP);
             }
-            /* Skip 1 cache entry */
+            /* Skip 5 cache entries */
             // _BINARY_OP_INPLACE_ADD_UNICODE
             {
                 PyObject *left_o = PyStackRef_AsPyObjectBorrow(left);
 
         TARGET(BINARY_OP_MULTIPLY_FLOAT) {
             frame->instr_ptr = next_instr;
-            next_instr += 2;
+            next_instr += 6;
             INSTRUCTION_STATS(BINARY_OP_MULTIPLY_FLOAT);
-            static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 1, "incorrect cache size");
+            static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5, "incorrect cache size");
             _PyStackRef left;
             _PyStackRef right;
             _PyStackRef res;
                 DEOPT_IF(!PyFloat_CheckExact(left_o), BINARY_OP);
                 DEOPT_IF(!PyFloat_CheckExact(right_o), BINARY_OP);
             }
-            /* Skip 1 cache entry */
+            /* Skip 5 cache entries */
             // _BINARY_OP_MULTIPLY_FLOAT
             {
                 PyObject *left_o = PyStackRef_AsPyObjectBorrow(left);
 
         TARGET(BINARY_OP_MULTIPLY_INT) {
             frame->instr_ptr = next_instr;
-            next_instr += 2;
+            next_instr += 6;
             INSTRUCTION_STATS(BINARY_OP_MULTIPLY_INT);
-            static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 1, "incorrect cache size");
+            static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5, "incorrect cache size");
             _PyStackRef left;
             _PyStackRef right;
             _PyStackRef res;
                 DEOPT_IF(!PyLong_CheckExact(left_o), BINARY_OP);
                 DEOPT_IF(!PyLong_CheckExact(right_o), BINARY_OP);
             }
-            /* Skip 1 cache entry */
+            /* Skip 5 cache entries */
             // _BINARY_OP_MULTIPLY_INT
             {
                 PyObject *left_o = PyStackRef_AsPyObjectBorrow(left);
 
         TARGET(BINARY_OP_SUBTRACT_FLOAT) {
             frame->instr_ptr = next_instr;
-            next_instr += 2;
+            next_instr += 6;
             INSTRUCTION_STATS(BINARY_OP_SUBTRACT_FLOAT);
-            static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 1, "incorrect cache size");
+            static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5, "incorrect cache size");
             _PyStackRef left;
             _PyStackRef right;
             _PyStackRef res;
                 DEOPT_IF(!PyFloat_CheckExact(left_o), BINARY_OP);
                 DEOPT_IF(!PyFloat_CheckExact(right_o), BINARY_OP);
             }
-            /* Skip 1 cache entry */
+            /* Skip 5 cache entries */
             // _BINARY_OP_SUBTRACT_FLOAT
             {
                 PyObject *left_o = PyStackRef_AsPyObjectBorrow(left);
 
         TARGET(BINARY_OP_SUBTRACT_INT) {
             frame->instr_ptr = next_instr;
-            next_instr += 2;
+            next_instr += 6;
             INSTRUCTION_STATS(BINARY_OP_SUBTRACT_INT);
-            static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 1, "incorrect cache size");
+            static_assert(INLINE_CACHE_ENTRIES_BINARY_OP == 5, "incorrect cache size");
             _PyStackRef left;
             _PyStackRef right;
             _PyStackRef res;
                 DEOPT_IF(!PyLong_CheckExact(left_o), BINARY_OP);
                 DEOPT_IF(!PyLong_CheckExact(right_o), BINARY_OP);
             }
-            /* Skip 1 cache entry */
+            /* Skip 5 cache entries */
             // _BINARY_OP_SUBTRACT_INT
             {
                 PyObject *left_o = PyStackRef_AsPyObjectBorrow(left);
index c5c008fcbe574ef379d52682a3095de8e5aa8504..cb6c33f01d35984eb9f37debc4961fd2ac9d3375 100644 (file)
@@ -152,6 +152,7 @@ static void *opcode_targets[256] = {
     &&TARGET_BINARY_OP_ADD_FLOAT,
     &&TARGET_BINARY_OP_ADD_INT,
     &&TARGET_BINARY_OP_ADD_UNICODE,
+    &&TARGET_BINARY_OP_EXTEND,
     &&TARGET_BINARY_OP_MULTIPLY_FLOAT,
     &&TARGET_BINARY_OP_MULTIPLY_INT,
     &&TARGET_BINARY_OP_SUBTRACT_FLOAT,
@@ -233,7 +234,6 @@ static void *opcode_targets[256] = {
     &&_unknown_opcode,
     &&_unknown_opcode,
     &&_unknown_opcode,
-    &&_unknown_opcode,
     &&TARGET_INSTRUMENTED_END_FOR,
     &&TARGET_INSTRUMENTED_POP_ITER,
     &&TARGET_INSTRUMENTED_END_SEND,
index aff4493fdc4dd7ac4bf7028b6f090de523c1fd6b..90838d274a5e873a454ee616adaa59321c73299c 100644 (file)
             break;
         }
 
+        case _GUARD_BINARY_OP_EXTEND: {
+            break;
+        }
+
+        case _BINARY_OP_EXTEND: {
+            _Py_UopsSymbol *res;
+            res = sym_new_not_null(ctx);
+            stack_pointer[-2] = res;
+            stack_pointer += -1;
+            assert(WITHIN_STACK_BOUNDS());
+            break;
+        }
+
         case _BINARY_SUBSCR: {
             _Py_UopsSymbol *res;
             res = sym_new_not_null(ctx);
index 8d9f19c88951877af4e331af57a4ecfb3c50c0cd..09bfcd34b5a543b46a73901ae19ba2d1cca8f259 100644 (file)
@@ -1174,7 +1174,7 @@ do_specialize_instance_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject*
             assert(tp_version != 0);
             write_u32(lm_cache->type_version, tp_version);
             /* borrowed */
-            write_obj(lm_cache->descr, fget);
+            write_ptr(lm_cache->descr, fget);
             specialize(instr, LOAD_ATTR_PROPERTY);
             return 0;
         }
@@ -1254,7 +1254,7 @@ do_specialize_instance_load_attr(PyObject* owner, _Py_CODEUNIT* instr, PyObject*
             #endif
             write_u32(lm_cache->keys_version, version);
             /* borrowed */
-            write_obj(lm_cache->descr, descr);
+            write_ptr(lm_cache->descr, descr);
             write_u32(lm_cache->type_version, tp_version);
             specialize(instr, LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN);
             return 0;
@@ -1534,7 +1534,7 @@ specialize_class_load_attr(PyObject *owner, _Py_CODEUNIT *instr,
             }
             #endif
             write_u32(cache->type_version, tp_version);
-            write_obj(cache->descr, descr);
+            write_ptr(cache->descr, descr);
             if (metaclass_check) {
                 write_u32(cache->keys_version, meta_version);
                 specialize(instr, LOAD_ATTR_CLASS_WITH_METACLASS_CHECK);
@@ -1642,7 +1642,7 @@ specialize_attr_loadclassattr(PyObject *owner, _Py_CODEUNIT *instr,
     *  working since Python 2.6 and it's battle-tested.
     */
     write_u32(cache->type_version, tp_version);
-    write_obj(cache->descr, descr);
+    write_ptr(cache->descr, descr);
     return 1;
 }
 
@@ -2412,6 +2412,92 @@ binary_op_fail_kind(int oparg, PyObject *lhs, PyObject *rhs)
 }
 #endif
 
+/** Binary Op Specialization Extensions */
+
+/* float-long */
+
+static int
+float_compactlong_guard(PyObject *lhs, PyObject *rhs)
+{
+    return (
+        PyFloat_CheckExact(lhs) &&
+        PyLong_CheckExact(rhs) &&
+        _PyLong_IsCompact((PyLongObject *)rhs)
+    );
+}
+
+#define FLOAT_LONG_ACTION(NAME, OP) \
+    static PyObject * \
+    (NAME)(PyObject *lhs, PyObject *rhs) \
+    { \
+        double lhs_val = PyFloat_AsDouble(lhs); \
+        Py_ssize_t rhs_val = _PyLong_CompactValue((PyLongObject *)rhs); \
+        return PyFloat_FromDouble(lhs_val OP rhs_val); \
+    }
+FLOAT_LONG_ACTION(float_compactlong_add, +)
+FLOAT_LONG_ACTION(float_compactlong_subtract, -)
+FLOAT_LONG_ACTION(float_compactlong_multiply, *)
+FLOAT_LONG_ACTION(float_compactlong_true_div, /)
+#undef FLOAT_LONG_ACTION
+
+/*  long-float */
+
+static int
+compactlong_float_guard(PyObject *lhs, PyObject *rhs)
+{
+    return (
+        PyFloat_CheckExact(rhs) &&
+        PyLong_CheckExact(lhs) &&
+        _PyLong_IsCompact((PyLongObject *)lhs)
+    );
+}
+
+#define LONG_FLOAT_ACTION(NAME, OP) \
+    static PyObject * \
+    (NAME)(PyObject *lhs, PyObject *rhs) \
+    { \
+        double rhs_val = PyFloat_AsDouble(rhs); \
+        Py_ssize_t lhs_val = _PyLong_CompactValue((PyLongObject *)lhs); \
+        return PyFloat_FromDouble(lhs_val OP rhs_val); \
+    }
+LONG_FLOAT_ACTION(compactlong_float_add, +)
+LONG_FLOAT_ACTION(compactlong_float_subtract, -)
+LONG_FLOAT_ACTION(compactlong_float_multiply, *)
+LONG_FLOAT_ACTION(compactlong_float_true_div, /)
+#undef LONG_FLOAT_ACTION
+
+static _PyBinaryOpSpecializationDescr float_compactlong_specs[NB_OPARG_LAST+1] = {
+    [NB_ADD] = {float_compactlong_guard, float_compactlong_add},
+    [NB_SUBTRACT] = {float_compactlong_guard, float_compactlong_subtract},
+    [NB_TRUE_DIVIDE] = {float_compactlong_guard, float_compactlong_true_div},
+    [NB_MULTIPLY] = {float_compactlong_guard, float_compactlong_multiply},
+};
+
+static _PyBinaryOpSpecializationDescr compactlong_float_specs[NB_OPARG_LAST+1] = {
+    [NB_ADD] = {compactlong_float_guard, compactlong_float_add},
+    [NB_SUBTRACT] = {compactlong_float_guard, compactlong_float_subtract},
+    [NB_TRUE_DIVIDE] = {compactlong_float_guard, compactlong_float_true_div},
+    [NB_MULTIPLY] = {compactlong_float_guard, compactlong_float_multiply},
+};
+
+static int
+binary_op_extended_specialization(PyObject *lhs, PyObject *rhs, int oparg,
+                                  _PyBinaryOpSpecializationDescr **descr)
+{
+#define LOOKUP_SPEC(TABLE, OPARG) \
+    if ((TABLE)[(OPARG)].action) { \
+        if ((TABLE)[(OPARG)].guard(lhs, rhs)) { \
+            *descr = &((TABLE)[OPARG]); \
+            return 1; \
+        } \
+    }
+
+    LOOKUP_SPEC(compactlong_float_specs, oparg);
+    LOOKUP_SPEC(float_compactlong_specs, oparg);
+#undef LOOKUP_SPEC
+    return 0;
+}
+
 void
 _Py_Specialize_BinaryOp(_PyStackRef lhs_st, _PyStackRef rhs_st, _Py_CODEUNIT *instr,
                         int oparg, _PyStackRef *locals)
@@ -2420,6 +2506,12 @@ _Py_Specialize_BinaryOp(_PyStackRef lhs_st, _PyStackRef rhs_st, _Py_CODEUNIT *in
     PyObject *rhs = PyStackRef_AsPyObjectBorrow(rhs_st);
     assert(ENABLE_SPECIALIZATION_FT);
     assert(_PyOpcode_Caches[BINARY_OP] == INLINE_CACHE_ENTRIES_BINARY_OP);
+
+    _PyBinaryOpCache *cache = (_PyBinaryOpCache *)(instr + 1);
+    if (instr->op.code == BINARY_OP_EXTEND) {
+        write_ptr(cache->external_cache, NULL);
+    }
+
     switch (oparg) {
         case NB_ADD:
         case NB_INPLACE_ADD:
@@ -2474,8 +2566,17 @@ _Py_Specialize_BinaryOp(_PyStackRef lhs_st, _PyStackRef rhs_st, _Py_CODEUNIT *in
             }
             break;
     }
+
+    _PyBinaryOpSpecializationDescr *descr;
+    if (binary_op_extended_specialization(lhs, rhs, oparg, &descr)) {
+        specialize(instr, BINARY_OP_EXTEND);
+        write_ptr(cache->external_cache, (void*)descr);
+        return;
+    }
+
     SPECIALIZATION_FAIL(BINARY_OP, binary_op_fail_kind(oparg, lhs, rhs));
     unspecialize(instr);
+    return;
 }
 
 
index c8c30a7985aa2e9c3fb1b865ea24655f002cc170..213165b06866b5c105c6c5b1a450b4be25b5ba19 100644 (file)
@@ -378,6 +378,8 @@ Python/pylifecycle.c        -       INTERPRETER_TRAMPOLINE_CODEDEF  -
 Python/pystate.c       -       initial -
 Python/specialize.c    -       adaptive_opcodes        -
 Python/specialize.c    -       cache_requirements      -
+Python/specialize.c    -       float_compactlong_specs -
+Python/specialize.c    -       compactlong_float_specs -
 Python/stdlib_module_names.h   -       _Py_stdlib_module_names -
 Python/sysmodule.c     -       perf_map_state  -
 Python/sysmodule.c     -       _PySys_ImplCacheTag     -
index de31d9b232f9dfc1c1d97b6908554acaf83a4eba..41b36b6a546360fe1df37b15c24a04d78e05c3ba 100644 (file)
@@ -357,9 +357,12 @@ class Parser(PLexer):
     def uop(self) -> UOp | None:
         if tkn := self.expect(lx.IDENTIFIER):
             if self.expect(lx.DIVIDE):
+                sign = 1
+                if negate := self.expect(lx.MINUS):
+                    sign = -1
                 if num := self.expect(lx.NUMBER):
                     try:
-                        size = int(num.text)
+                        size = sign * int(num.text)
                     except ValueError:
                         raise self.make_syntax_error(
                             f"Expected integer, got {num.text!r}"