From 59b37f77ff2f458c3f0464594e905465610602bf Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Sat, 26 Apr 2025 17:46:05 +0200 Subject: [PATCH 01/13] Optimize CALL_ISINSTANCE --- Include/internal/pycore_uop_ids.h | 382 +++++++++++++++--------------- Lib/test/test_capi/test_opt.py | 94 ++++++++ Python/bytecodes.c | 7 +- Python/optimizer_bytecodes.c | 25 ++ Python/optimizer_cases.c.h | 27 ++- 5 files changed, 342 insertions(+), 193 deletions(-) diff --git a/Include/internal/pycore_uop_ids.h b/Include/internal/pycore_uop_ids.h index d6d81f88c8e00c..193fb351de5be4 100644 --- a/Include/internal/pycore_uop_ids.h +++ b/Include/internal/pycore_uop_ids.h @@ -40,122 +40,122 @@ extern "C" { #define _CALL_BUILTIN_O 322 #define _CALL_INTRINSIC_1 CALL_INTRINSIC_1 #define _CALL_INTRINSIC_2 CALL_INTRINSIC_2 -#define _CALL_ISINSTANCE CALL_ISINSTANCE -#define _CALL_KW_NON_PY 323 +#define _CALL_ISINSTANCE 323 +#define _CALL_KW_NON_PY 324 #define _CALL_LEN CALL_LEN #define _CALL_LIST_APPEND CALL_LIST_APPEND -#define _CALL_METHOD_DESCRIPTOR_FAST 324 -#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 325 -#define _CALL_METHOD_DESCRIPTOR_NOARGS 326 -#define _CALL_METHOD_DESCRIPTOR_O 327 -#define _CALL_NON_PY_GENERAL 328 -#define _CALL_STR_1 329 -#define _CALL_TUPLE_1 330 -#define _CALL_TYPE_1 331 -#define _CHECK_AND_ALLOCATE_OBJECT 332 -#define _CHECK_ATTR_CLASS 333 -#define _CHECK_ATTR_METHOD_LAZY_DICT 334 -#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS 335 +#define _CALL_METHOD_DESCRIPTOR_FAST 325 +#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 326 +#define _CALL_METHOD_DESCRIPTOR_NOARGS 327 +#define _CALL_METHOD_DESCRIPTOR_O 328 +#define _CALL_NON_PY_GENERAL 329 +#define _CALL_STR_1 330 +#define _CALL_TUPLE_1 331 +#define _CALL_TYPE_1 332 +#define _CHECK_AND_ALLOCATE_OBJECT 333 +#define _CHECK_ATTR_CLASS 334 +#define _CHECK_ATTR_METHOD_LAZY_DICT 335 +#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS 336 #define _CHECK_EG_MATCH CHECK_EG_MATCH #define _CHECK_EXC_MATCH CHECK_EXC_MATCH -#define _CHECK_FUNCTION 336 -#define _CHECK_FUNCTION_EXACT_ARGS 337 -#define _CHECK_FUNCTION_VERSION 338 -#define _CHECK_FUNCTION_VERSION_INLINE 339 -#define _CHECK_FUNCTION_VERSION_KW 340 -#define _CHECK_IS_NOT_PY_CALLABLE 341 -#define _CHECK_IS_NOT_PY_CALLABLE_KW 342 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES 343 -#define _CHECK_METHOD_VERSION 344 -#define _CHECK_METHOD_VERSION_KW 345 -#define _CHECK_PEP_523 346 -#define _CHECK_PERIODIC 347 -#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM 348 -#define _CHECK_STACK_SPACE 349 -#define _CHECK_STACK_SPACE_OPERAND 350 -#define _CHECK_VALIDITY 351 -#define _COMPARE_OP 352 -#define _COMPARE_OP_FLOAT 353 -#define _COMPARE_OP_INT 354 -#define _COMPARE_OP_STR 355 -#define _CONTAINS_OP 356 -#define _CONTAINS_OP_DICT 357 -#define _CONTAINS_OP_SET 358 +#define _CHECK_FUNCTION 337 +#define _CHECK_FUNCTION_EXACT_ARGS 338 +#define _CHECK_FUNCTION_VERSION 339 +#define _CHECK_FUNCTION_VERSION_INLINE 340 +#define _CHECK_FUNCTION_VERSION_KW 341 +#define _CHECK_IS_NOT_PY_CALLABLE 342 +#define _CHECK_IS_NOT_PY_CALLABLE_KW 343 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES 344 +#define _CHECK_METHOD_VERSION 345 +#define _CHECK_METHOD_VERSION_KW 346 +#define _CHECK_PEP_523 347 +#define _CHECK_PERIODIC 348 +#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM 349 +#define _CHECK_STACK_SPACE 350 +#define _CHECK_STACK_SPACE_OPERAND 351 +#define _CHECK_VALIDITY 352 +#define _COMPARE_OP 353 +#define _COMPARE_OP_FLOAT 354 +#define _COMPARE_OP_INT 355 +#define _COMPARE_OP_STR 356 +#define _CONTAINS_OP 357 +#define _CONTAINS_OP_DICT 358 +#define _CONTAINS_OP_SET 359 #define _CONVERT_VALUE CONVERT_VALUE #define _COPY COPY #define _COPY_FREE_VARS COPY_FREE_VARS -#define _CREATE_INIT_FRAME 359 +#define _CREATE_INIT_FRAME 360 #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 360 +#define _DEOPT 361 #define _DICT_MERGE DICT_MERGE #define _DICT_UPDATE DICT_UPDATE -#define _DO_CALL 361 -#define _DO_CALL_FUNCTION_EX 362 -#define _DO_CALL_KW 363 +#define _DO_CALL 362 +#define _DO_CALL_FUNCTION_EX 363 +#define _DO_CALL_KW 364 #define _END_FOR END_FOR #define _END_SEND END_SEND -#define _ERROR_POP_N 364 +#define _ERROR_POP_N 365 #define _EXIT_INIT_CHECK EXIT_INIT_CHECK -#define _EXPAND_METHOD 365 -#define _EXPAND_METHOD_KW 366 -#define _FATAL_ERROR 367 +#define _EXPAND_METHOD 366 +#define _EXPAND_METHOD_KW 367 +#define _FATAL_ERROR 368 #define _FORMAT_SIMPLE FORMAT_SIMPLE #define _FORMAT_WITH_SPEC FORMAT_WITH_SPEC -#define _FOR_ITER 368 -#define _FOR_ITER_GEN_FRAME 369 -#define _FOR_ITER_TIER_TWO 370 +#define _FOR_ITER 369 +#define _FOR_ITER_GEN_FRAME 370 +#define _FOR_ITER_TIER_TWO 371 #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_BINARY_OP_EXTEND 371 -#define _GUARD_CALLABLE_STR_1 372 -#define _GUARD_CALLABLE_TUPLE_1 373 -#define _GUARD_CALLABLE_TYPE_1 374 -#define _GUARD_DORV_NO_DICT 375 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 376 -#define _GUARD_GLOBALS_VERSION 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_DICT 383 -#define _GUARD_NOS_FLOAT 384 -#define _GUARD_NOS_INT 385 -#define _GUARD_NOS_LIST 386 -#define _GUARD_NOS_NULL 387 -#define _GUARD_NOS_TUPLE 388 -#define _GUARD_NOS_UNICODE 389 -#define _GUARD_NOT_EXHAUSTED_LIST 390 -#define _GUARD_NOT_EXHAUSTED_RANGE 391 -#define _GUARD_NOT_EXHAUSTED_TUPLE 392 -#define _GUARD_TOS_ANY_SET 393 -#define _GUARD_TOS_DICT 394 -#define _GUARD_TOS_FLOAT 395 -#define _GUARD_TOS_INT 396 -#define _GUARD_TOS_LIST 397 -#define _GUARD_TOS_TUPLE 398 -#define _GUARD_TOS_UNICODE 399 -#define _GUARD_TYPE_VERSION 400 -#define _GUARD_TYPE_VERSION_AND_LOCK 401 +#define _GUARD_BINARY_OP_EXTEND 372 +#define _GUARD_CALLABLE_STR_1 373 +#define _GUARD_CALLABLE_TUPLE_1 374 +#define _GUARD_CALLABLE_TYPE_1 375 +#define _GUARD_DORV_NO_DICT 376 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 377 +#define _GUARD_GLOBALS_VERSION 378 +#define _GUARD_IS_FALSE_POP 379 +#define _GUARD_IS_NONE_POP 380 +#define _GUARD_IS_NOT_NONE_POP 381 +#define _GUARD_IS_TRUE_POP 382 +#define _GUARD_KEYS_VERSION 383 +#define _GUARD_NOS_DICT 384 +#define _GUARD_NOS_FLOAT 385 +#define _GUARD_NOS_INT 386 +#define _GUARD_NOS_LIST 387 +#define _GUARD_NOS_NULL 388 +#define _GUARD_NOS_TUPLE 389 +#define _GUARD_NOS_UNICODE 390 +#define _GUARD_NOT_EXHAUSTED_LIST 391 +#define _GUARD_NOT_EXHAUSTED_RANGE 392 +#define _GUARD_NOT_EXHAUSTED_TUPLE 393 +#define _GUARD_TOS_ANY_SET 394 +#define _GUARD_TOS_DICT 395 +#define _GUARD_TOS_FLOAT 396 +#define _GUARD_TOS_INT 397 +#define _GUARD_TOS_LIST 398 +#define _GUARD_TOS_TUPLE 399 +#define _GUARD_TOS_UNICODE 400 +#define _GUARD_TYPE_VERSION 401 +#define _GUARD_TYPE_VERSION_AND_LOCK 402 #define _IMPORT_FROM IMPORT_FROM #define _IMPORT_NAME IMPORT_NAME -#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 402 -#define _INIT_CALL_PY_EXACT_ARGS 403 -#define _INIT_CALL_PY_EXACT_ARGS_0 404 -#define _INIT_CALL_PY_EXACT_ARGS_1 405 -#define _INIT_CALL_PY_EXACT_ARGS_2 406 -#define _INIT_CALL_PY_EXACT_ARGS_3 407 -#define _INIT_CALL_PY_EXACT_ARGS_4 408 -#define _INSERT_NULL 409 +#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 403 +#define _INIT_CALL_PY_EXACT_ARGS 404 +#define _INIT_CALL_PY_EXACT_ARGS_0 405 +#define _INIT_CALL_PY_EXACT_ARGS_1 406 +#define _INIT_CALL_PY_EXACT_ARGS_2 407 +#define _INIT_CALL_PY_EXACT_ARGS_3 408 +#define _INIT_CALL_PY_EXACT_ARGS_4 409 +#define _INSERT_NULL 410 #define _INSTRUMENTED_FOR_ITER INSTRUMENTED_FOR_ITER #define _INSTRUMENTED_INSTRUCTION INSTRUMENTED_INSTRUCTION #define _INSTRUMENTED_JUMP_FORWARD INSTRUMENTED_JUMP_FORWARD @@ -165,163 +165,163 @@ extern "C" { #define _INSTRUMENTED_POP_JUMP_IF_NONE INSTRUMENTED_POP_JUMP_IF_NONE #define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE INSTRUMENTED_POP_JUMP_IF_NOT_NONE #define _INSTRUMENTED_POP_JUMP_IF_TRUE INSTRUMENTED_POP_JUMP_IF_TRUE -#define _IS_NONE 410 +#define _IS_NONE 411 #define _IS_OP IS_OP -#define _ITER_CHECK_LIST 411 -#define _ITER_CHECK_RANGE 412 -#define _ITER_CHECK_TUPLE 413 -#define _ITER_JUMP_LIST 414 -#define _ITER_JUMP_RANGE 415 -#define _ITER_JUMP_TUPLE 416 -#define _ITER_NEXT_LIST 417 -#define _ITER_NEXT_LIST_TIER_TWO 418 -#define _ITER_NEXT_RANGE 419 -#define _ITER_NEXT_TUPLE 420 -#define _JUMP_TO_TOP 421 +#define _ITER_CHECK_LIST 412 +#define _ITER_CHECK_RANGE 413 +#define _ITER_CHECK_TUPLE 414 +#define _ITER_JUMP_LIST 415 +#define _ITER_JUMP_RANGE 416 +#define _ITER_JUMP_TUPLE 417 +#define _ITER_NEXT_LIST 418 +#define _ITER_NEXT_LIST_TIER_TWO 419 +#define _ITER_NEXT_RANGE 420 +#define _ITER_NEXT_TUPLE 421 +#define _JUMP_TO_TOP 422 #define _LIST_APPEND LIST_APPEND #define _LIST_EXTEND LIST_EXTEND -#define _LOAD_ATTR 422 -#define _LOAD_ATTR_CLASS 423 +#define _LOAD_ATTR 423 +#define _LOAD_ATTR_CLASS 424 #define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN -#define _LOAD_ATTR_INSTANCE_VALUE 424 -#define _LOAD_ATTR_METHOD_LAZY_DICT 425 -#define _LOAD_ATTR_METHOD_NO_DICT 426 -#define _LOAD_ATTR_METHOD_WITH_VALUES 427 -#define _LOAD_ATTR_MODULE 428 -#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 429 -#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 430 -#define _LOAD_ATTR_PROPERTY_FRAME 431 -#define _LOAD_ATTR_SLOT 432 -#define _LOAD_ATTR_WITH_HINT 433 +#define _LOAD_ATTR_INSTANCE_VALUE 425 +#define _LOAD_ATTR_METHOD_LAZY_DICT 426 +#define _LOAD_ATTR_METHOD_NO_DICT 427 +#define _LOAD_ATTR_METHOD_WITH_VALUES 428 +#define _LOAD_ATTR_MODULE 429 +#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 430 +#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 431 +#define _LOAD_ATTR_PROPERTY_FRAME 432 +#define _LOAD_ATTR_SLOT 433 +#define _LOAD_ATTR_WITH_HINT 434 #define _LOAD_BUILD_CLASS LOAD_BUILD_CLASS -#define _LOAD_BYTECODE 434 +#define _LOAD_BYTECODE 435 #define _LOAD_COMMON_CONSTANT LOAD_COMMON_CONSTANT #define _LOAD_CONST LOAD_CONST #define _LOAD_CONST_IMMORTAL LOAD_CONST_IMMORTAL -#define _LOAD_CONST_INLINE 435 -#define _LOAD_CONST_INLINE_BORROW 436 +#define _LOAD_CONST_INLINE 436 +#define _LOAD_CONST_INLINE_BORROW 437 #define _LOAD_CONST_MORTAL LOAD_CONST_MORTAL #define _LOAD_DEREF LOAD_DEREF -#define _LOAD_FAST 437 -#define _LOAD_FAST_0 438 -#define _LOAD_FAST_1 439 -#define _LOAD_FAST_2 440 -#define _LOAD_FAST_3 441 -#define _LOAD_FAST_4 442 -#define _LOAD_FAST_5 443 -#define _LOAD_FAST_6 444 -#define _LOAD_FAST_7 445 +#define _LOAD_FAST 438 +#define _LOAD_FAST_0 439 +#define _LOAD_FAST_1 440 +#define _LOAD_FAST_2 441 +#define _LOAD_FAST_3 442 +#define _LOAD_FAST_4 443 +#define _LOAD_FAST_5 444 +#define _LOAD_FAST_6 445 +#define _LOAD_FAST_7 446 #define _LOAD_FAST_AND_CLEAR LOAD_FAST_AND_CLEAR -#define _LOAD_FAST_BORROW 446 -#define _LOAD_FAST_BORROW_0 447 -#define _LOAD_FAST_BORROW_1 448 -#define _LOAD_FAST_BORROW_2 449 -#define _LOAD_FAST_BORROW_3 450 -#define _LOAD_FAST_BORROW_4 451 -#define _LOAD_FAST_BORROW_5 452 -#define _LOAD_FAST_BORROW_6 453 -#define _LOAD_FAST_BORROW_7 454 +#define _LOAD_FAST_BORROW 447 +#define _LOAD_FAST_BORROW_0 448 +#define _LOAD_FAST_BORROW_1 449 +#define _LOAD_FAST_BORROW_2 450 +#define _LOAD_FAST_BORROW_3 451 +#define _LOAD_FAST_BORROW_4 452 +#define _LOAD_FAST_BORROW_5 453 +#define _LOAD_FAST_BORROW_6 454 +#define _LOAD_FAST_BORROW_7 455 #define _LOAD_FAST_BORROW_LOAD_FAST_BORROW LOAD_FAST_BORROW_LOAD_FAST_BORROW #define _LOAD_FAST_CHECK LOAD_FAST_CHECK #define _LOAD_FAST_LOAD_FAST LOAD_FAST_LOAD_FAST #define _LOAD_FROM_DICT_OR_DEREF LOAD_FROM_DICT_OR_DEREF #define _LOAD_FROM_DICT_OR_GLOBALS LOAD_FROM_DICT_OR_GLOBALS -#define _LOAD_GLOBAL 455 -#define _LOAD_GLOBAL_BUILTINS 456 -#define _LOAD_GLOBAL_MODULE 457 +#define _LOAD_GLOBAL 456 +#define _LOAD_GLOBAL_BUILTINS 457 +#define _LOAD_GLOBAL_MODULE 458 #define _LOAD_LOCALS LOAD_LOCALS #define _LOAD_NAME LOAD_NAME -#define _LOAD_SMALL_INT 458 -#define _LOAD_SMALL_INT_0 459 -#define _LOAD_SMALL_INT_1 460 -#define _LOAD_SMALL_INT_2 461 -#define _LOAD_SMALL_INT_3 462 -#define _LOAD_SPECIAL 463 +#define _LOAD_SMALL_INT 459 +#define _LOAD_SMALL_INT_0 460 +#define _LOAD_SMALL_INT_1 461 +#define _LOAD_SMALL_INT_2 462 +#define _LOAD_SMALL_INT_3 463 +#define _LOAD_SPECIAL 464 #define _LOAD_SUPER_ATTR_ATTR LOAD_SUPER_ATTR_ATTR #define _LOAD_SUPER_ATTR_METHOD LOAD_SUPER_ATTR_METHOD -#define _MAKE_CALLARGS_A_TUPLE 464 +#define _MAKE_CALLARGS_A_TUPLE 465 #define _MAKE_CELL MAKE_CELL #define _MAKE_FUNCTION MAKE_FUNCTION -#define _MAKE_WARM 465 +#define _MAKE_WARM 466 #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 466 -#define _MAYBE_EXPAND_METHOD_KW 467 -#define _MONITOR_CALL 468 -#define _MONITOR_CALL_KW 469 -#define _MONITOR_JUMP_BACKWARD 470 -#define _MONITOR_RESUME 471 +#define _MAYBE_EXPAND_METHOD 467 +#define _MAYBE_EXPAND_METHOD_KW 468 +#define _MONITOR_CALL 469 +#define _MONITOR_CALL_KW 470 +#define _MONITOR_JUMP_BACKWARD 471 +#define _MONITOR_RESUME 472 #define _NOP NOP #define _POP_EXCEPT POP_EXCEPT -#define _POP_JUMP_IF_FALSE 472 -#define _POP_JUMP_IF_TRUE 473 +#define _POP_JUMP_IF_FALSE 473 +#define _POP_JUMP_IF_TRUE 474 #define _POP_TOP POP_TOP -#define _POP_TOP_LOAD_CONST_INLINE 474 -#define _POP_TOP_LOAD_CONST_INLINE_BORROW 475 -#define _POP_TWO_LOAD_CONST_INLINE_BORROW 476 +#define _POP_TOP_LOAD_CONST_INLINE 475 +#define _POP_TOP_LOAD_CONST_INLINE_BORROW 476 +#define _POP_TWO_LOAD_CONST_INLINE_BORROW 477 #define _PUSH_EXC_INFO PUSH_EXC_INFO -#define _PUSH_FRAME 477 +#define _PUSH_FRAME 478 #define _PUSH_NULL PUSH_NULL -#define _PUSH_NULL_CONDITIONAL 478 -#define _PY_FRAME_GENERAL 479 -#define _PY_FRAME_KW 480 -#define _QUICKEN_RESUME 481 -#define _REPLACE_WITH_TRUE 482 +#define _PUSH_NULL_CONDITIONAL 479 +#define _PY_FRAME_GENERAL 480 +#define _PY_FRAME_KW 481 +#define _QUICKEN_RESUME 482 +#define _REPLACE_WITH_TRUE 483 #define _RESUME_CHECK RESUME_CHECK #define _RETURN_GENERATOR RETURN_GENERATOR #define _RETURN_VALUE RETURN_VALUE -#define _SAVE_RETURN_OFFSET 483 -#define _SEND 484 -#define _SEND_GEN_FRAME 485 +#define _SAVE_RETURN_OFFSET 484 +#define _SEND 485 +#define _SEND_GEN_FRAME 486 #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 486 -#define _STORE_ATTR 487 -#define _STORE_ATTR_INSTANCE_VALUE 488 -#define _STORE_ATTR_SLOT 489 -#define _STORE_ATTR_WITH_HINT 490 +#define _START_EXECUTOR 487 +#define _STORE_ATTR 488 +#define _STORE_ATTR_INSTANCE_VALUE 489 +#define _STORE_ATTR_SLOT 490 +#define _STORE_ATTR_WITH_HINT 491 #define _STORE_DEREF STORE_DEREF -#define _STORE_FAST 491 -#define _STORE_FAST_0 492 -#define _STORE_FAST_1 493 -#define _STORE_FAST_2 494 -#define _STORE_FAST_3 495 -#define _STORE_FAST_4 496 -#define _STORE_FAST_5 497 -#define _STORE_FAST_6 498 -#define _STORE_FAST_7 499 +#define _STORE_FAST 492 +#define _STORE_FAST_0 493 +#define _STORE_FAST_1 494 +#define _STORE_FAST_2 495 +#define _STORE_FAST_3 496 +#define _STORE_FAST_4 497 +#define _STORE_FAST_5 498 +#define _STORE_FAST_6 499 +#define _STORE_FAST_7 500 #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 500 -#define _STORE_SUBSCR 501 -#define _STORE_SUBSCR_DICT 502 -#define _STORE_SUBSCR_LIST_INT 503 +#define _STORE_SLICE 501 +#define _STORE_SUBSCR 502 +#define _STORE_SUBSCR_DICT 503 +#define _STORE_SUBSCR_LIST_INT 504 #define _SWAP SWAP -#define _TIER2_RESUME_CHECK 504 -#define _TO_BOOL 505 +#define _TIER2_RESUME_CHECK 505 +#define _TO_BOOL 506 #define _TO_BOOL_BOOL TO_BOOL_BOOL #define _TO_BOOL_INT TO_BOOL_INT -#define _TO_BOOL_LIST 506 +#define _TO_BOOL_LIST 507 #define _TO_BOOL_NONE TO_BOOL_NONE -#define _TO_BOOL_STR 507 +#define _TO_BOOL_STR 508 #define _UNARY_INVERT UNARY_INVERT #define _UNARY_NEGATIVE UNARY_NEGATIVE #define _UNARY_NOT UNARY_NOT #define _UNPACK_EX UNPACK_EX -#define _UNPACK_SEQUENCE 508 -#define _UNPACK_SEQUENCE_LIST 509 -#define _UNPACK_SEQUENCE_TUPLE 510 -#define _UNPACK_SEQUENCE_TWO_TUPLE 511 +#define _UNPACK_SEQUENCE 509 +#define _UNPACK_SEQUENCE_LIST 510 +#define _UNPACK_SEQUENCE_TUPLE 511 +#define _UNPACK_SEQUENCE_TWO_TUPLE 512 #define _WITH_EXCEPT_START WITH_EXCEPT_START #define _YIELD_VALUE YIELD_VALUE -#define MAX_UOP_ID 511 +#define MAX_UOP_ID 512 #ifdef __cplusplus } diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py index 7e0c60d5522402..93f7a42fb8c4a3 100644 --- a/Lib/test/test_capi/test_opt.py +++ b/Lib/test/test_capi/test_opt.py @@ -1940,6 +1940,100 @@ def testfunc(n): self.assertNotIn("_COMPARE_OP_INT", uops) self.assertNotIn("_GUARD_IS_TRUE_POP", uops) + def test_call_isinstance_is_true(self): + def testfunc(n): + x = 0 + for _ in range(n): + y = isinstance(42, int) + if y: + x += 1 + return x + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_CALL_ISINSTANCE", uops) + self.assertNotIn("_TO_BOOL_BOOL", uops) + self.assertNotIn("_GUARD_IS_TRUE_POP", uops) + + def test_call_isinstance_is_false(self): + def testfunc(n): + x = 0 + for _ in range(n): + y = isinstance(42, str) + if not y: + x += 1 + return x + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_CALL_ISINSTANCE", uops) + self.assertNotIn("_TO_BOOL_BOOL", uops) + self.assertNotIn("_GUARD_IS_FALSE_POP", uops) + + def test_call_isinstance_subclass(self): + def testfunc(n): + x = 0 + for _ in range(n): + y = isinstance(True, int) + if y: + x += 1 + return x + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_CALL_ISINSTANCE", uops) + self.assertNotIn("_TO_BOOL_BOOL", uops) + self.assertNotIn("_GUARD_IS_TRUE_POP", uops) + + def test_call_isinstance_unknown_object(self): + def testfunc(n): + class Foo: + bar = 42 + + x = 0 + for _ in range(n): + # we only know bar (LOAD_ATTR) is not null (set via sym_new_not_null) + bar = Foo.bar + # This will only narrow to bool and not to True due to 'bar' having + # unknown (non-null) type + y = isinstance(bar, int) + if y: + x += 1 + return x + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_CALL_ISINSTANCE", uops) + self.assertNotIn("_TO_BOOL_BOOL", uops) + self.assertIn("_GUARD_IS_TRUE_POP", uops) + + def test_call_isinstance_tuple_of_classes(self): + def testfunc(n): + x = 0 + for _ in range(n): + # The optimization currently only narrows to bool + # the seconds argument is a tuple of classes. + y = isinstance(42, (int, str)) + if y: + x += 1 + return x + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_CALL_ISINSTANCE", uops) + self.assertNotIn("_TO_BOOL_BOOL", uops) + self.assertIn("_GUARD_IS_TRUE_POP", uops) + def global_identity(x): return x diff --git a/Python/bytecodes.c b/Python/bytecodes.c index 6592bc57ed20a1..bbd76350308941 100644 --- a/Python/bytecodes.c +++ b/Python/bytecodes.c @@ -4284,7 +4284,7 @@ dummy_func( res = PyStackRef_FromPyObjectSteal(res_o); } - inst(CALL_ISINSTANCE, (unused/1, unused/2, callable, self_or_null, args[oparg] -- res)) { + op(_CALL_ISINSTANCE, (callable, self_or_null, args[oparg] -- res)) { /* isinstance(o, o2) */ PyObject *callable_o = PyStackRef_AsPyObjectBorrow(callable); @@ -4309,6 +4309,11 @@ dummy_func( DECREF_INPUTS(); } + macro(CALL_ISINSTANCE) = + unused/1 + + unused/2 + + _CALL_ISINSTANCE; + // This is secretly a super-instruction inst(CALL_LIST_APPEND, (unused/1, unused/2, callable, self, arg -- )) { assert(oparg == 1); diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index 567caad22554ea..1b5fa56edd1e9f 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -886,6 +886,31 @@ dummy_func(void) { } } + op(_CALL_ISINSTANCE, (callable, self_or_null, args[oparg] -- res)) { + if (sym_is_null(self_or_null) || sym_is_not_null(self_or_null)) { + if (sym_is_not_null(self_or_null)) { + args--; + } + JitOptSymbol *cls_sym = args[1]; + JitOptSymbol *inst_sym = args[0]; + if(sym_is_const(ctx, cls_sym) && sym_matches_type(cls_sym, &PyType_Type)) { + PyTypeObject *cls = (PyTypeObject *)sym_get_const(ctx, cls_sym); + if (sym_matches_type(inst_sym, cls)) { + res = sym_new_const(ctx, Py_True); + } + else { + res = sym_new_type(ctx, &PyBool_Type); + } + } + else { + res = sym_new_type(ctx, &PyBool_Type); + } + } + else { + res = sym_new_type(ctx, &PyBool_Type); + } + } + op(_GUARD_IS_TRUE_POP, (flag -- )) { if (sym_is_const(ctx, flag)) { PyObject *value = sym_get_const(ctx, flag); diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index 679240b6efa315..3e36e9b1944c05 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -2042,8 +2042,33 @@ } case _CALL_ISINSTANCE: { + JitOptSymbol **args; + JitOptSymbol *self_or_null; JitOptSymbol *res; - res = sym_new_not_null(ctx); + args = &stack_pointer[-oparg]; + self_or_null = stack_pointer[-1 - oparg]; + if (sym_is_null(self_or_null) || sym_is_not_null(self_or_null)) { + if (sym_is_not_null(self_or_null)) { + args--; + } + JitOptSymbol *cls_sym = args[1]; + JitOptSymbol *inst_sym = args[0]; + if(sym_is_const(ctx, cls_sym) && sym_matches_type(cls_sym, &PyType_Type)) { + PyTypeObject *cls = (PyTypeObject *)sym_get_const(ctx, cls_sym); + if (sym_matches_type(inst_sym, cls)) { + res = sym_new_const(ctx, Py_True); + } + else { + res = sym_new_type(ctx, &PyBool_Type); + } + } + else { + res = sym_new_type(ctx, &PyBool_Type); + } + } + else { + res = sym_new_type(ctx, &PyBool_Type); + } stack_pointer[-2 - oparg] = res; stack_pointer += -1 - oparg; assert(WITHIN_STACK_BOUNDS()); From a81c02e030a1341f09d05e4a51b1519c91729d23 Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Sat, 26 Apr 2025 17:50:06 +0200 Subject: [PATCH 02/13] Add news entry --- .../2025-04-26-17-50-01.gh-issue-131798.XiOgw5.rst | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 Misc/NEWS.d/next/Core_and_Builtins/2025-04-26-17-50-01.gh-issue-131798.XiOgw5.rst diff --git a/Misc/NEWS.d/next/Core_and_Builtins/2025-04-26-17-50-01.gh-issue-131798.XiOgw5.rst b/Misc/NEWS.d/next/Core_and_Builtins/2025-04-26-17-50-01.gh-issue-131798.XiOgw5.rst new file mode 100644 index 00000000000000..45ab1bea6b1dd7 --- /dev/null +++ b/Misc/NEWS.d/next/Core_and_Builtins/2025-04-26-17-50-01.gh-issue-131798.XiOgw5.rst @@ -0,0 +1,2 @@ +Narrow the return type and constant-evaluate ``CALL_ISINSTANCE`` for a +subset of known values in the JIT. Patch by Tomas Roun From b1eb6a07e989a9716dc0c23c259950c4dc477e45 Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Tue, 29 Apr 2025 23:13:35 +0200 Subject: [PATCH 03/13] Optimize for subclasses as well --- Lib/test/test_capi/test_opt.py | 2 +- Python/optimizer_bytecodes.c | 17 +++++++++++++++-- Python/optimizer_cases.c.h | 10 ++++++++-- 3 files changed, 24 insertions(+), 5 deletions(-) diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py index 93f7a42fb8c4a3..f210c4b60adef7 100644 --- a/Lib/test/test_capi/test_opt.py +++ b/Lib/test/test_capi/test_opt.py @@ -2020,7 +2020,7 @@ def testfunc(n): x = 0 for _ in range(n): # The optimization currently only narrows to bool - # the seconds argument is a tuple of classes. + # when the second argument is a tuple of classes. y = isinstance(42, (int, str)) if y: x += 1 diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index 1b5fa56edd1e9f..d4b0f8739e965b 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -893,16 +893,29 @@ dummy_func(void) { } JitOptSymbol *cls_sym = args[1]; JitOptSymbol *inst_sym = args[0]; + if(sym_is_const(ctx, cls_sym) && sym_matches_type(cls_sym, &PyType_Type)) { + // isinstance(obj, cls) where cls is a known class PyTypeObject *cls = (PyTypeObject *)sym_get_const(ctx, cls_sym); - if (sym_matches_type(inst_sym, cls)) { - res = sym_new_const(ctx, Py_True); + + if (sym_has_type(inst_sym)) { + // isinstance(obj, cls) where both obj and cls have known types + // We can deduce either True or False + PyTypeObject *inst_type = sym_get_type(inst_sym); + if (sym_matches_type(inst_sym, cls) || PyType_IsSubtype(inst_type, cls)) { + res = sym_new_const(ctx, Py_True); + } + else { + res = sym_new_const(ctx, Py_False); + } } else { + // isinstance(obj, cls) where obj has unknown type res = sym_new_type(ctx, &PyBool_Type); } } else { + // isinstance(obj, cls) where cls has unknown type res = sym_new_type(ctx, &PyBool_Type); } } diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index 3e36e9b1944c05..e3f9f9cc5df0a7 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -2055,8 +2055,14 @@ JitOptSymbol *inst_sym = args[0]; if(sym_is_const(ctx, cls_sym) && sym_matches_type(cls_sym, &PyType_Type)) { PyTypeObject *cls = (PyTypeObject *)sym_get_const(ctx, cls_sym); - if (sym_matches_type(inst_sym, cls)) { - res = sym_new_const(ctx, Py_True); + if (sym_has_type(inst_sym)) { + PyTypeObject *inst_type = sym_get_type(inst_sym); + if (sym_matches_type(inst_sym, cls) || PyType_IsSubtype(inst_type, cls)) { + res = sym_new_const(ctx, Py_True); + } + else { + res = sym_new_const(ctx, Py_False); + } } else { res = sym_new_type(ctx, &PyBool_Type); From 770f7edffed1f993332f7dfaa6736474adff937f Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Thu, 8 May 2025 23:37:46 +0200 Subject: [PATCH 04/13] Regen cases --- Include/internal/pycore_uop_ids.h | 390 +++++++++++++++--------------- 1 file changed, 197 insertions(+), 193 deletions(-) diff --git a/Include/internal/pycore_uop_ids.h b/Include/internal/pycore_uop_ids.h index 666e245ddb505b..0e9e734bbb4d62 100644 --- a/Include/internal/pycore_uop_ids.h +++ b/Include/internal/pycore_uop_ids.h @@ -43,126 +43,125 @@ extern "C" { #define _CALL_BUILTIN_O 323 #define _CALL_INTRINSIC_1 CALL_INTRINSIC_1 #define _CALL_INTRINSIC_2 CALL_INTRINSIC_2 -#define _CALL_ISINSTANCE 323 -#define _CALL_KW_NON_PY 324 -#define _CALL_LEN CALL_LEN +#define _CALL_ISINSTANCE 324 +#define _CALL_KW_NON_PY 325 +#define _CALL_LEN 326 #define _CALL_LIST_APPEND CALL_LIST_APPEND -#define _CALL_METHOD_DESCRIPTOR_FAST 325 -#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 326 -#define _CALL_METHOD_DESCRIPTOR_NOARGS 327 -#define _CALL_METHOD_DESCRIPTOR_O 328 -#define _CALL_NON_PY_GENERAL 329 -#define _CALL_STR_1 330 -#define _CALL_TUPLE_1 331 -#define _CALL_TYPE_1 332 -#define _CHECK_AND_ALLOCATE_OBJECT 333 -#define _CHECK_ATTR_CLASS 334 -#define _CHECK_ATTR_METHOD_LAZY_DICT 335 -#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS 336 +#define _CALL_METHOD_DESCRIPTOR_FAST 327 +#define _CALL_METHOD_DESCRIPTOR_FAST_WITH_KEYWORDS 328 +#define _CALL_METHOD_DESCRIPTOR_NOARGS 329 +#define _CALL_METHOD_DESCRIPTOR_O 330 +#define _CALL_NON_PY_GENERAL 331 +#define _CALL_STR_1 332 +#define _CALL_TUPLE_1 333 +#define _CALL_TYPE_1 334 +#define _CHECK_AND_ALLOCATE_OBJECT 335 +#define _CHECK_ATTR_CLASS 336 +#define _CHECK_ATTR_METHOD_LAZY_DICT 337 +#define _CHECK_CALL_BOUND_METHOD_EXACT_ARGS 338 #define _CHECK_EG_MATCH CHECK_EG_MATCH #define _CHECK_EXC_MATCH CHECK_EXC_MATCH -#define _CHECK_FUNCTION 337 -#define _CHECK_FUNCTION_EXACT_ARGS 338 -#define _CHECK_FUNCTION_VERSION 339 -#define _CHECK_FUNCTION_VERSION_INLINE 340 -#define _CHECK_FUNCTION_VERSION_KW 341 -#define _CHECK_IS_NOT_PY_CALLABLE 342 -#define _CHECK_IS_NOT_PY_CALLABLE_KW 343 -#define _CHECK_MANAGED_OBJECT_HAS_VALUES 344 -#define _CHECK_METHOD_VERSION 345 -#define _CHECK_METHOD_VERSION_KW 346 -#define _CHECK_PEP_523 347 -#define _CHECK_PERIODIC 348 -#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM 349 -#define _CHECK_STACK_SPACE 350 -#define _CHECK_STACK_SPACE_OPERAND 351 -#define _CHECK_VALIDITY 352 -#define _COMPARE_OP 353 -#define _COMPARE_OP_FLOAT 354 -#define _COMPARE_OP_INT 355 -#define _COMPARE_OP_STR 356 -#define _CONTAINS_OP 357 -#define _CONTAINS_OP_DICT 358 -#define _CONTAINS_OP_SET 359 +#define _CHECK_FUNCTION 339 +#define _CHECK_FUNCTION_EXACT_ARGS 340 +#define _CHECK_FUNCTION_VERSION 341 +#define _CHECK_FUNCTION_VERSION_INLINE 342 +#define _CHECK_FUNCTION_VERSION_KW 343 +#define _CHECK_IS_NOT_PY_CALLABLE 344 +#define _CHECK_IS_NOT_PY_CALLABLE_KW 345 +#define _CHECK_MANAGED_OBJECT_HAS_VALUES 346 +#define _CHECK_METHOD_VERSION 347 +#define _CHECK_METHOD_VERSION_KW 348 +#define _CHECK_PEP_523 349 +#define _CHECK_PERIODIC 350 +#define _CHECK_PERIODIC_IF_NOT_YIELD_FROM 351 +#define _CHECK_RECURSION_REMAINING 352 +#define _CHECK_STACK_SPACE 353 +#define _CHECK_STACK_SPACE_OPERAND 354 +#define _CHECK_VALIDITY 355 +#define _COMPARE_OP 356 +#define _COMPARE_OP_FLOAT 357 +#define _COMPARE_OP_INT 358 +#define _COMPARE_OP_STR 359 +#define _CONTAINS_OP 360 +#define _CONTAINS_OP_DICT 361 +#define _CONTAINS_OP_SET 362 #define _CONVERT_VALUE CONVERT_VALUE #define _COPY COPY #define _COPY_FREE_VARS COPY_FREE_VARS -#define _CREATE_INIT_FRAME 360 +#define _CREATE_INIT_FRAME 363 #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 361 +#define _DEOPT 364 #define _DICT_MERGE DICT_MERGE #define _DICT_UPDATE DICT_UPDATE -#define _DO_CALL 362 -#define _DO_CALL_FUNCTION_EX 363 -#define _DO_CALL_KW 364 +#define _DO_CALL 365 +#define _DO_CALL_FUNCTION_EX 366 +#define _DO_CALL_KW 367 #define _END_FOR END_FOR #define _END_SEND END_SEND -#define _ERROR_POP_N 365 +#define _ERROR_POP_N 368 #define _EXIT_INIT_CHECK EXIT_INIT_CHECK -<<<<<<< HEAD -#define _EXPAND_METHOD 366 -#define _FATAL_ERROR 368 -#define _EXPAND_METHOD 368 -#define _EXPAND_METHOD_KW 369 -#define _FATAL_ERROR 370 ->>>>>>> main +#define _EXPAND_METHOD 369 +#define _EXPAND_METHOD_KW 370 +#define _FATAL_ERROR 371 #define _FORMAT_SIMPLE FORMAT_SIMPLE #define _FORMAT_WITH_SPEC FORMAT_WITH_SPEC -#define _FOR_ITER 369 -#define _FOR_ITER_GEN_FRAME 370 -#define _FOR_ITER_TIER_TWO 371 +#define _FOR_ITER 372 +#define _FOR_ITER_GEN_FRAME 373 +#define _FOR_ITER_TIER_TWO 374 #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_BINARY_OP_EXTEND 372 -#define _GUARD_CALLABLE_STR_1 373 -#define _GUARD_CALLABLE_TUPLE_1 374 -#define _GUARD_CALLABLE_TYPE_1 375 -#define _GUARD_DORV_NO_DICT 376 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 377 -#define _GUARD_GLOBALS_VERSION 378 -#define _GUARD_IS_FALSE_POP 379 -#define _GUARD_IS_NONE_POP 380 -#define _GUARD_IS_NOT_NONE_POP 381 -#define _GUARD_IS_TRUE_POP 382 -#define _GUARD_KEYS_VERSION 383 -#define _GUARD_NOS_DICT 384 -#define _GUARD_NOS_FLOAT 385 -#define _GUARD_NOS_INT 386 -#define _GUARD_NOS_LIST 387 -#define _GUARD_NOS_NULL 388 -#define _GUARD_NOS_TUPLE 389 -#define _GUARD_NOS_UNICODE 390 -#define _GUARD_NOT_EXHAUSTED_LIST 391 -#define _GUARD_NOT_EXHAUSTED_RANGE 392 -#define _GUARD_NOT_EXHAUSTED_TUPLE 393 -#define _GUARD_TOS_ANY_SET 394 -#define _GUARD_TOS_DICT 395 -#define _GUARD_TOS_FLOAT 396 -#define _GUARD_TOS_INT 397 -#define _GUARD_TOS_LIST 398 -#define _GUARD_TOS_TUPLE 399 -#define _GUARD_TOS_UNICODE 400 -#define _GUARD_TYPE_VERSION 401 -#define _GUARD_TYPE_VERSION_AND_LOCK 402 +#define _GUARD_BINARY_OP_EXTEND 375 +#define _GUARD_CALLABLE_LEN 376 +#define _GUARD_CALLABLE_STR_1 377 +#define _GUARD_CALLABLE_TUPLE_1 378 +#define _GUARD_CALLABLE_TYPE_1 379 +#define _GUARD_DORV_NO_DICT 380 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 381 +#define _GUARD_GLOBALS_VERSION 382 +#define _GUARD_IS_FALSE_POP 383 +#define _GUARD_IS_NONE_POP 384 +#define _GUARD_IS_NOT_NONE_POP 385 +#define _GUARD_IS_TRUE_POP 386 +#define _GUARD_KEYS_VERSION 387 +#define _GUARD_NOS_DICT 388 +#define _GUARD_NOS_FLOAT 389 +#define _GUARD_NOS_INT 390 +#define _GUARD_NOS_LIST 391 +#define _GUARD_NOS_NULL 392 +#define _GUARD_NOS_TUPLE 393 +#define _GUARD_NOS_UNICODE 394 +#define _GUARD_NOT_EXHAUSTED_LIST 395 +#define _GUARD_NOT_EXHAUSTED_RANGE 396 +#define _GUARD_NOT_EXHAUSTED_TUPLE 397 +#define _GUARD_TOS_ANY_SET 398 +#define _GUARD_TOS_DICT 399 +#define _GUARD_TOS_FLOAT 400 +#define _GUARD_TOS_INT 401 +#define _GUARD_TOS_LIST 402 +#define _GUARD_TOS_SLICE 403 +#define _GUARD_TOS_TUPLE 404 +#define _GUARD_TOS_UNICODE 405 +#define _GUARD_TYPE_VERSION 406 +#define _GUARD_TYPE_VERSION_AND_LOCK 407 #define _IMPORT_FROM IMPORT_FROM #define _IMPORT_NAME IMPORT_NAME -#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 403 -#define _INIT_CALL_PY_EXACT_ARGS 404 -#define _INIT_CALL_PY_EXACT_ARGS_0 405 -#define _INIT_CALL_PY_EXACT_ARGS_1 406 -#define _INIT_CALL_PY_EXACT_ARGS_2 407 -#define _INIT_CALL_PY_EXACT_ARGS_3 408 -#define _INIT_CALL_PY_EXACT_ARGS_4 409 -#define _INSERT_NULL 410 +#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 408 +#define _INIT_CALL_PY_EXACT_ARGS 409 +#define _INIT_CALL_PY_EXACT_ARGS_0 410 +#define _INIT_CALL_PY_EXACT_ARGS_1 411 +#define _INIT_CALL_PY_EXACT_ARGS_2 412 +#define _INIT_CALL_PY_EXACT_ARGS_3 413 +#define _INIT_CALL_PY_EXACT_ARGS_4 414 +#define _INSERT_NULL 415 #define _INSTRUMENTED_FOR_ITER INSTRUMENTED_FOR_ITER #define _INSTRUMENTED_INSTRUCTION INSTRUMENTED_INSTRUCTION #define _INSTRUMENTED_JUMP_FORWARD INSTRUMENTED_JUMP_FORWARD @@ -172,158 +171,163 @@ extern "C" { #define _INSTRUMENTED_POP_JUMP_IF_NONE INSTRUMENTED_POP_JUMP_IF_NONE #define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE INSTRUMENTED_POP_JUMP_IF_NOT_NONE #define _INSTRUMENTED_POP_JUMP_IF_TRUE INSTRUMENTED_POP_JUMP_IF_TRUE -#define _IS_NONE 411 +#define _IS_NONE 416 #define _IS_OP IS_OP -#define _ITER_CHECK_LIST 412 -#define _ITER_CHECK_RANGE 413 -#define _ITER_CHECK_TUPLE 414 -#define _ITER_JUMP_LIST 415 -#define _ITER_JUMP_RANGE 416 -#define _ITER_NEXT_LIST 418 -#define _ITER_NEXT_LIST_TIER_TWO 419 -#define _ITER_NEXT_RANGE 420 -#define _ITER_NEXT_TUPLE 421 -#define _JUMP_TO_TOP 422 +#define _ITER_CHECK_LIST 417 +#define _ITER_CHECK_RANGE 418 +#define _ITER_CHECK_TUPLE 419 +#define _ITER_JUMP_LIST 420 +#define _ITER_JUMP_RANGE 421 +#define _ITER_JUMP_TUPLE 422 +#define _ITER_NEXT_LIST 423 +#define _ITER_NEXT_LIST_TIER_TWO 424 +#define _ITER_NEXT_RANGE 425 +#define _ITER_NEXT_TUPLE 426 +#define _JUMP_TO_TOP 427 +#define _LIST_APPEND LIST_APPEND +#define _LIST_EXTEND LIST_EXTEND +#define _LOAD_ATTR 428 +#define _LOAD_ATTR_CLASS 429 #define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN -#define _LOAD_ATTR_INSTANCE_VALUE 425 -#define _LOAD_ATTR_METHOD_LAZY_DICT 426 -#define _LOAD_ATTR_METHOD_NO_DICT 427 -#define _LOAD_ATTR_METHOD_WITH_VALUES 428 -#define _LOAD_ATTR_MODULE 429 -#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 430 -#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 431 -#define _LOAD_ATTR_PROPERTY_FRAME 432 -#define _LOAD_ATTR_SLOT 433 -#define _LOAD_ATTR_WITH_HINT 434 +#define _LOAD_ATTR_INSTANCE_VALUE 430 +#define _LOAD_ATTR_METHOD_LAZY_DICT 431 +#define _LOAD_ATTR_METHOD_NO_DICT 432 +#define _LOAD_ATTR_METHOD_WITH_VALUES 433 +#define _LOAD_ATTR_MODULE 434 +#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 435 +#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 436 +#define _LOAD_ATTR_PROPERTY_FRAME 437 +#define _LOAD_ATTR_SLOT 438 +#define _LOAD_ATTR_WITH_HINT 439 #define _LOAD_BUILD_CLASS LOAD_BUILD_CLASS -#define _LOAD_BYTECODE 435 +#define _LOAD_BYTECODE 440 #define _LOAD_COMMON_CONSTANT LOAD_COMMON_CONSTANT #define _LOAD_CONST LOAD_CONST #define _LOAD_CONST_IMMORTAL LOAD_CONST_IMMORTAL -#define _LOAD_CONST_INLINE 436 -#define _LOAD_CONST_INLINE_BORROW 437 +#define _LOAD_CONST_INLINE 441 +#define _LOAD_CONST_INLINE_BORROW 442 #define _LOAD_CONST_MORTAL LOAD_CONST_MORTAL #define _LOAD_DEREF LOAD_DEREF -#define _LOAD_FAST 438 -#define _LOAD_FAST_0 439 -#define _LOAD_FAST_1 440 -#define _LOAD_FAST_2 441 -#define _LOAD_FAST_3 442 -#define _LOAD_FAST_4 443 -#define _LOAD_FAST_5 444 -#define _LOAD_FAST_6 445 -#define _LOAD_FAST_7 446 +#define _LOAD_FAST 443 +#define _LOAD_FAST_0 444 +#define _LOAD_FAST_1 445 +#define _LOAD_FAST_2 446 +#define _LOAD_FAST_3 447 +#define _LOAD_FAST_4 448 +#define _LOAD_FAST_5 449 +#define _LOAD_FAST_6 450 +#define _LOAD_FAST_7 451 #define _LOAD_FAST_AND_CLEAR LOAD_FAST_AND_CLEAR -#define _LOAD_FAST_BORROW 447 -#define _LOAD_FAST_BORROW_0 448 -#define _LOAD_FAST_BORROW_1 449 -#define _LOAD_FAST_BORROW_2 450 -#define _LOAD_FAST_BORROW_3 451 -#define _LOAD_FAST_BORROW_4 452 -#define _LOAD_FAST_BORROW_5 453 -#define _LOAD_FAST_BORROW_6 454 -#define _LOAD_FAST_BORROW_7 455 +#define _LOAD_FAST_BORROW 452 +#define _LOAD_FAST_BORROW_0 453 +#define _LOAD_FAST_BORROW_1 454 +#define _LOAD_FAST_BORROW_2 455 +#define _LOAD_FAST_BORROW_3 456 +#define _LOAD_FAST_BORROW_4 457 +#define _LOAD_FAST_BORROW_5 458 +#define _LOAD_FAST_BORROW_6 459 +#define _LOAD_FAST_BORROW_7 460 #define _LOAD_FAST_BORROW_LOAD_FAST_BORROW LOAD_FAST_BORROW_LOAD_FAST_BORROW #define _LOAD_FAST_CHECK LOAD_FAST_CHECK #define _LOAD_FAST_LOAD_FAST LOAD_FAST_LOAD_FAST #define _LOAD_FROM_DICT_OR_DEREF LOAD_FROM_DICT_OR_DEREF #define _LOAD_FROM_DICT_OR_GLOBALS LOAD_FROM_DICT_OR_GLOBALS -#define _LOAD_GLOBAL 456 -#define _LOAD_GLOBAL_BUILTINS 457 -#define _LOAD_GLOBAL_MODULE 458 +#define _LOAD_GLOBAL 461 +#define _LOAD_GLOBAL_BUILTINS 462 +#define _LOAD_GLOBAL_MODULE 463 #define _LOAD_LOCALS LOAD_LOCALS #define _LOAD_NAME LOAD_NAME -#define _LOAD_SMALL_INT 459 -#define _LOAD_SMALL_INT_0 460 -#define _LOAD_SMALL_INT_1 461 -#define _LOAD_SMALL_INT_2 462 -#define _LOAD_SMALL_INT_3 463 -#define _LOAD_SPECIAL 464 +#define _LOAD_SMALL_INT 464 +#define _LOAD_SMALL_INT_0 465 +#define _LOAD_SMALL_INT_1 466 +#define _LOAD_SMALL_INT_2 467 +#define _LOAD_SMALL_INT_3 468 +#define _LOAD_SPECIAL 469 #define _LOAD_SUPER_ATTR_ATTR LOAD_SUPER_ATTR_ATTR #define _LOAD_SUPER_ATTR_METHOD LOAD_SUPER_ATTR_METHOD -#define _MAKE_CALLARGS_A_TUPLE 465 +#define _MAKE_CALLARGS_A_TUPLE 470 #define _MAKE_CELL MAKE_CELL #define _MAKE_FUNCTION MAKE_FUNCTION -#define _MAKE_WARM 466 +#define _MAKE_WARM 471 #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 467 -#define _MAYBE_EXPAND_METHOD_KW 468 -#define _MONITOR_CALL 469 -#define _MONITOR_CALL_KW 470 -#define _MONITOR_JUMP_BACKWARD 471 -#define _MONITOR_RESUME 472 +#define _MAYBE_EXPAND_METHOD 472 +#define _MAYBE_EXPAND_METHOD_KW 473 +#define _MONITOR_CALL 474 +#define _MONITOR_CALL_KW 475 +#define _MONITOR_JUMP_BACKWARD 476 +#define _MONITOR_RESUME 477 #define _NOP NOP #define _POP_EXCEPT POP_EXCEPT -#define _POP_JUMP_IF_FALSE 473 -#define _POP_JUMP_IF_TRUE 474 +#define _POP_JUMP_IF_FALSE 478 +#define _POP_JUMP_IF_TRUE 479 #define _POP_TOP POP_TOP -#define _POP_TOP_LOAD_CONST_INLINE 475 -#define _POP_TOP_LOAD_CONST_INLINE_BORROW 476 -#define _POP_TWO_LOAD_CONST_INLINE_BORROW 477 +#define _POP_TOP_LOAD_CONST_INLINE 480 +#define _POP_TOP_LOAD_CONST_INLINE_BORROW 481 +#define _POP_TWO_LOAD_CONST_INLINE_BORROW 482 #define _PUSH_EXC_INFO PUSH_EXC_INFO -#define _PUSH_FRAME 478 +#define _PUSH_FRAME 483 #define _PUSH_NULL PUSH_NULL -#define _PUSH_NULL_CONDITIONAL 479 -#define _PY_FRAME_GENERAL 480 -#define _PY_FRAME_KW 481 -#define _QUICKEN_RESUME 482 -#define _REPLACE_WITH_TRUE 483 +#define _PUSH_NULL_CONDITIONAL 484 +#define _PY_FRAME_GENERAL 485 +#define _PY_FRAME_KW 486 +#define _QUICKEN_RESUME 487 +#define _REPLACE_WITH_TRUE 488 #define _RESUME_CHECK RESUME_CHECK #define _RETURN_GENERATOR RETURN_GENERATOR #define _RETURN_VALUE RETURN_VALUE -#define _SAVE_RETURN_OFFSET 484 -#define _SEND 485 -#define _SEND_GEN_FRAME 486 +#define _SAVE_RETURN_OFFSET 489 +#define _SEND 490 +#define _SEND_GEN_FRAME 491 #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 487 -#define _STORE_ATTR 488 -#define _STORE_ATTR_INSTANCE_VALUE 489 -#define _STORE_ATTR_SLOT 490 -#define _STORE_ATTR_WITH_HINT 491 +#define _START_EXECUTOR 492 +#define _STORE_ATTR 493 +#define _STORE_ATTR_INSTANCE_VALUE 494 +#define _STORE_ATTR_SLOT 495 +#define _STORE_ATTR_WITH_HINT 496 #define _STORE_DEREF STORE_DEREF -#define _STORE_FAST 492 -#define _STORE_FAST_0 493 -#define _STORE_FAST_1 494 -#define _STORE_FAST_2 495 -#define _STORE_FAST_3 496 -#define _STORE_FAST_4 497 -#define _STORE_FAST_5 498 -#define _STORE_FAST_6 499 -#define _STORE_FAST_7 500 +#define _STORE_FAST 497 +#define _STORE_FAST_0 498 +#define _STORE_FAST_1 499 +#define _STORE_FAST_2 500 +#define _STORE_FAST_3 501 +#define _STORE_FAST_4 502 +#define _STORE_FAST_5 503 +#define _STORE_FAST_6 504 +#define _STORE_FAST_7 505 #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 501 -#define _STORE_SUBSCR 502 -#define _STORE_SUBSCR_DICT 503 -#define _STORE_SUBSCR_LIST_INT 504 +#define _STORE_SLICE 506 +#define _STORE_SUBSCR 507 +#define _STORE_SUBSCR_DICT 508 +#define _STORE_SUBSCR_LIST_INT 509 #define _SWAP SWAP -#define _TIER2_RESUME_CHECK 505 -#define _TO_BOOL 506 +#define _TIER2_RESUME_CHECK 510 +#define _TO_BOOL 511 #define _TO_BOOL_BOOL TO_BOOL_BOOL #define _TO_BOOL_INT TO_BOOL_INT -#define _TO_BOOL_LIST 507 +#define _TO_BOOL_LIST 512 #define _TO_BOOL_NONE TO_BOOL_NONE -#define _TO_BOOL_STR 508 +#define _TO_BOOL_STR 513 #define _UNARY_INVERT UNARY_INVERT #define _UNARY_NEGATIVE UNARY_NEGATIVE #define _UNARY_NOT UNARY_NOT #define _UNPACK_EX UNPACK_EX -#define _UNPACK_SEQUENCE 509 -#define _UNPACK_SEQUENCE_LIST 510 -#define _UNPACK_SEQUENCE_TUPLE 511 -#define _UNPACK_SEQUENCE_TWO_TUPLE 512 +#define _UNPACK_SEQUENCE 514 +#define _UNPACK_SEQUENCE_LIST 515 +#define _UNPACK_SEQUENCE_TUPLE 516 +#define _UNPACK_SEQUENCE_TWO_TUPLE 517 #define _WITH_EXCEPT_START WITH_EXCEPT_START #define _YIELD_VALUE YIELD_VALUE -#define MAX_UOP_ID 512 +#define MAX_UOP_ID 517 #ifdef __cplusplus } From 3e86810996d0ab276368916742a752ab0df16723 Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Thu, 8 May 2025 23:39:32 +0200 Subject: [PATCH 05/13] Add a comment --- Python/optimizer_bytecodes.c | 1 + 1 file changed, 1 insertion(+) diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index a9035c4e1c0747..c2d4284019c920 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -902,6 +902,7 @@ dummy_func(void) { // isinstance(obj, cls) where both obj and cls have known types // We can deduce either True or False PyTypeObject *inst_type = sym_get_type(inst_sym); + // The below check is equivalent to PyObject_TypeCheck(inst, cls) if (sym_matches_type(inst_sym, cls) || PyType_IsSubtype(inst_type, cls)) { res = sym_new_const(ctx, Py_True); } From 60d21fa0a1ae1498a86120d84ea652c98d2a33cd Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Thu, 8 May 2025 23:55:53 +0200 Subject: [PATCH 06/13] Simplify --- Include/internal/pycore_uop_ids.h | 288 +++++++++++++++--------------- Python/optimizer_bytecodes.c | 48 ++--- Python/optimizer_cases.c.h | 20 ++- 3 files changed, 178 insertions(+), 178 deletions(-) diff --git a/Include/internal/pycore_uop_ids.h b/Include/internal/pycore_uop_ids.h index 0e9e734bbb4d62..71a288a3a39179 100644 --- a/Include/internal/pycore_uop_ids.h +++ b/Include/internal/pycore_uop_ids.h @@ -120,48 +120,50 @@ extern "C" { #define _GET_LEN GET_LEN #define _GET_YIELD_FROM_ITER GET_YIELD_FROM_ITER #define _GUARD_BINARY_OP_EXTEND 375 -#define _GUARD_CALLABLE_LEN 376 -#define _GUARD_CALLABLE_STR_1 377 -#define _GUARD_CALLABLE_TUPLE_1 378 -#define _GUARD_CALLABLE_TYPE_1 379 -#define _GUARD_DORV_NO_DICT 380 -#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 381 -#define _GUARD_GLOBALS_VERSION 382 -#define _GUARD_IS_FALSE_POP 383 -#define _GUARD_IS_NONE_POP 384 -#define _GUARD_IS_NOT_NONE_POP 385 -#define _GUARD_IS_TRUE_POP 386 -#define _GUARD_KEYS_VERSION 387 -#define _GUARD_NOS_DICT 388 -#define _GUARD_NOS_FLOAT 389 -#define _GUARD_NOS_INT 390 -#define _GUARD_NOS_LIST 391 -#define _GUARD_NOS_NULL 392 -#define _GUARD_NOS_TUPLE 393 -#define _GUARD_NOS_UNICODE 394 -#define _GUARD_NOT_EXHAUSTED_LIST 395 -#define _GUARD_NOT_EXHAUSTED_RANGE 396 -#define _GUARD_NOT_EXHAUSTED_TUPLE 397 -#define _GUARD_TOS_ANY_SET 398 -#define _GUARD_TOS_DICT 399 -#define _GUARD_TOS_FLOAT 400 -#define _GUARD_TOS_INT 401 -#define _GUARD_TOS_LIST 402 -#define _GUARD_TOS_SLICE 403 -#define _GUARD_TOS_TUPLE 404 -#define _GUARD_TOS_UNICODE 405 -#define _GUARD_TYPE_VERSION 406 -#define _GUARD_TYPE_VERSION_AND_LOCK 407 +#define _GUARD_CALLABLE_ISINSTANCE 376 +#define _GUARD_CALLABLE_LEN 377 +#define _GUARD_CALLABLE_STR_1 378 +#define _GUARD_CALLABLE_TUPLE_1 379 +#define _GUARD_CALLABLE_TYPE_1 380 +#define _GUARD_DORV_NO_DICT 381 +#define _GUARD_DORV_VALUES_INST_ATTR_FROM_DICT 382 +#define _GUARD_GLOBALS_VERSION 383 +#define _GUARD_IS_FALSE_POP 384 +#define _GUARD_IS_NONE_POP 385 +#define _GUARD_IS_NOT_NONE_POP 386 +#define _GUARD_IS_TRUE_POP 387 +#define _GUARD_KEYS_VERSION 388 +#define _GUARD_NOS_DICT 389 +#define _GUARD_NOS_FLOAT 390 +#define _GUARD_NOS_INT 391 +#define _GUARD_NOS_LIST 392 +#define _GUARD_NOS_NULL 393 +#define _GUARD_NOS_TUPLE 394 +#define _GUARD_NOS_UNICODE 395 +#define _GUARD_NOT_EXHAUSTED_LIST 396 +#define _GUARD_NOT_EXHAUSTED_RANGE 397 +#define _GUARD_NOT_EXHAUSTED_TUPLE 398 +#define _GUARD_THIRD_NULL 399 +#define _GUARD_TOS_ANY_SET 400 +#define _GUARD_TOS_DICT 401 +#define _GUARD_TOS_FLOAT 402 +#define _GUARD_TOS_INT 403 +#define _GUARD_TOS_LIST 404 +#define _GUARD_TOS_SLICE 405 +#define _GUARD_TOS_TUPLE 406 +#define _GUARD_TOS_UNICODE 407 +#define _GUARD_TYPE_VERSION 408 +#define _GUARD_TYPE_VERSION_AND_LOCK 409 #define _IMPORT_FROM IMPORT_FROM #define _IMPORT_NAME IMPORT_NAME -#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 408 -#define _INIT_CALL_PY_EXACT_ARGS 409 -#define _INIT_CALL_PY_EXACT_ARGS_0 410 -#define _INIT_CALL_PY_EXACT_ARGS_1 411 -#define _INIT_CALL_PY_EXACT_ARGS_2 412 -#define _INIT_CALL_PY_EXACT_ARGS_3 413 -#define _INIT_CALL_PY_EXACT_ARGS_4 414 -#define _INSERT_NULL 415 +#define _INIT_CALL_BOUND_METHOD_EXACT_ARGS 410 +#define _INIT_CALL_PY_EXACT_ARGS 411 +#define _INIT_CALL_PY_EXACT_ARGS_0 412 +#define _INIT_CALL_PY_EXACT_ARGS_1 413 +#define _INIT_CALL_PY_EXACT_ARGS_2 414 +#define _INIT_CALL_PY_EXACT_ARGS_3 415 +#define _INIT_CALL_PY_EXACT_ARGS_4 416 +#define _INSERT_NULL 417 #define _INSTRUMENTED_FOR_ITER INSTRUMENTED_FOR_ITER #define _INSTRUMENTED_INSTRUCTION INSTRUMENTED_INSTRUCTION #define _INSTRUMENTED_JUMP_FORWARD INSTRUMENTED_JUMP_FORWARD @@ -171,163 +173,163 @@ extern "C" { #define _INSTRUMENTED_POP_JUMP_IF_NONE INSTRUMENTED_POP_JUMP_IF_NONE #define _INSTRUMENTED_POP_JUMP_IF_NOT_NONE INSTRUMENTED_POP_JUMP_IF_NOT_NONE #define _INSTRUMENTED_POP_JUMP_IF_TRUE INSTRUMENTED_POP_JUMP_IF_TRUE -#define _IS_NONE 416 +#define _IS_NONE 418 #define _IS_OP IS_OP -#define _ITER_CHECK_LIST 417 -#define _ITER_CHECK_RANGE 418 -#define _ITER_CHECK_TUPLE 419 -#define _ITER_JUMP_LIST 420 -#define _ITER_JUMP_RANGE 421 -#define _ITER_JUMP_TUPLE 422 -#define _ITER_NEXT_LIST 423 -#define _ITER_NEXT_LIST_TIER_TWO 424 -#define _ITER_NEXT_RANGE 425 -#define _ITER_NEXT_TUPLE 426 -#define _JUMP_TO_TOP 427 +#define _ITER_CHECK_LIST 419 +#define _ITER_CHECK_RANGE 420 +#define _ITER_CHECK_TUPLE 421 +#define _ITER_JUMP_LIST 422 +#define _ITER_JUMP_RANGE 423 +#define _ITER_JUMP_TUPLE 424 +#define _ITER_NEXT_LIST 425 +#define _ITER_NEXT_LIST_TIER_TWO 426 +#define _ITER_NEXT_RANGE 427 +#define _ITER_NEXT_TUPLE 428 +#define _JUMP_TO_TOP 429 #define _LIST_APPEND LIST_APPEND #define _LIST_EXTEND LIST_EXTEND -#define _LOAD_ATTR 428 -#define _LOAD_ATTR_CLASS 429 +#define _LOAD_ATTR 430 +#define _LOAD_ATTR_CLASS 431 #define _LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN LOAD_ATTR_GETATTRIBUTE_OVERRIDDEN -#define _LOAD_ATTR_INSTANCE_VALUE 430 -#define _LOAD_ATTR_METHOD_LAZY_DICT 431 -#define _LOAD_ATTR_METHOD_NO_DICT 432 -#define _LOAD_ATTR_METHOD_WITH_VALUES 433 -#define _LOAD_ATTR_MODULE 434 -#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 435 -#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 436 -#define _LOAD_ATTR_PROPERTY_FRAME 437 -#define _LOAD_ATTR_SLOT 438 -#define _LOAD_ATTR_WITH_HINT 439 +#define _LOAD_ATTR_INSTANCE_VALUE 432 +#define _LOAD_ATTR_METHOD_LAZY_DICT 433 +#define _LOAD_ATTR_METHOD_NO_DICT 434 +#define _LOAD_ATTR_METHOD_WITH_VALUES 435 +#define _LOAD_ATTR_MODULE 436 +#define _LOAD_ATTR_NONDESCRIPTOR_NO_DICT 437 +#define _LOAD_ATTR_NONDESCRIPTOR_WITH_VALUES 438 +#define _LOAD_ATTR_PROPERTY_FRAME 439 +#define _LOAD_ATTR_SLOT 440 +#define _LOAD_ATTR_WITH_HINT 441 #define _LOAD_BUILD_CLASS LOAD_BUILD_CLASS -#define _LOAD_BYTECODE 440 +#define _LOAD_BYTECODE 442 #define _LOAD_COMMON_CONSTANT LOAD_COMMON_CONSTANT #define _LOAD_CONST LOAD_CONST #define _LOAD_CONST_IMMORTAL LOAD_CONST_IMMORTAL -#define _LOAD_CONST_INLINE 441 -#define _LOAD_CONST_INLINE_BORROW 442 +#define _LOAD_CONST_INLINE 443 +#define _LOAD_CONST_INLINE_BORROW 444 #define _LOAD_CONST_MORTAL LOAD_CONST_MORTAL #define _LOAD_DEREF LOAD_DEREF -#define _LOAD_FAST 443 -#define _LOAD_FAST_0 444 -#define _LOAD_FAST_1 445 -#define _LOAD_FAST_2 446 -#define _LOAD_FAST_3 447 -#define _LOAD_FAST_4 448 -#define _LOAD_FAST_5 449 -#define _LOAD_FAST_6 450 -#define _LOAD_FAST_7 451 +#define _LOAD_FAST 445 +#define _LOAD_FAST_0 446 +#define _LOAD_FAST_1 447 +#define _LOAD_FAST_2 448 +#define _LOAD_FAST_3 449 +#define _LOAD_FAST_4 450 +#define _LOAD_FAST_5 451 +#define _LOAD_FAST_6 452 +#define _LOAD_FAST_7 453 #define _LOAD_FAST_AND_CLEAR LOAD_FAST_AND_CLEAR -#define _LOAD_FAST_BORROW 452 -#define _LOAD_FAST_BORROW_0 453 -#define _LOAD_FAST_BORROW_1 454 -#define _LOAD_FAST_BORROW_2 455 -#define _LOAD_FAST_BORROW_3 456 -#define _LOAD_FAST_BORROW_4 457 -#define _LOAD_FAST_BORROW_5 458 -#define _LOAD_FAST_BORROW_6 459 -#define _LOAD_FAST_BORROW_7 460 +#define _LOAD_FAST_BORROW 454 +#define _LOAD_FAST_BORROW_0 455 +#define _LOAD_FAST_BORROW_1 456 +#define _LOAD_FAST_BORROW_2 457 +#define _LOAD_FAST_BORROW_3 458 +#define _LOAD_FAST_BORROW_4 459 +#define _LOAD_FAST_BORROW_5 460 +#define _LOAD_FAST_BORROW_6 461 +#define _LOAD_FAST_BORROW_7 462 #define _LOAD_FAST_BORROW_LOAD_FAST_BORROW LOAD_FAST_BORROW_LOAD_FAST_BORROW #define _LOAD_FAST_CHECK LOAD_FAST_CHECK #define _LOAD_FAST_LOAD_FAST LOAD_FAST_LOAD_FAST #define _LOAD_FROM_DICT_OR_DEREF LOAD_FROM_DICT_OR_DEREF #define _LOAD_FROM_DICT_OR_GLOBALS LOAD_FROM_DICT_OR_GLOBALS -#define _LOAD_GLOBAL 461 -#define _LOAD_GLOBAL_BUILTINS 462 -#define _LOAD_GLOBAL_MODULE 463 +#define _LOAD_GLOBAL 463 +#define _LOAD_GLOBAL_BUILTINS 464 +#define _LOAD_GLOBAL_MODULE 465 #define _LOAD_LOCALS LOAD_LOCALS #define _LOAD_NAME LOAD_NAME -#define _LOAD_SMALL_INT 464 -#define _LOAD_SMALL_INT_0 465 -#define _LOAD_SMALL_INT_1 466 -#define _LOAD_SMALL_INT_2 467 -#define _LOAD_SMALL_INT_3 468 -#define _LOAD_SPECIAL 469 +#define _LOAD_SMALL_INT 466 +#define _LOAD_SMALL_INT_0 467 +#define _LOAD_SMALL_INT_1 468 +#define _LOAD_SMALL_INT_2 469 +#define _LOAD_SMALL_INT_3 470 +#define _LOAD_SPECIAL 471 #define _LOAD_SUPER_ATTR_ATTR LOAD_SUPER_ATTR_ATTR #define _LOAD_SUPER_ATTR_METHOD LOAD_SUPER_ATTR_METHOD -#define _MAKE_CALLARGS_A_TUPLE 470 +#define _MAKE_CALLARGS_A_TUPLE 472 #define _MAKE_CELL MAKE_CELL #define _MAKE_FUNCTION MAKE_FUNCTION -#define _MAKE_WARM 471 +#define _MAKE_WARM 473 #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 472 -#define _MAYBE_EXPAND_METHOD_KW 473 -#define _MONITOR_CALL 474 -#define _MONITOR_CALL_KW 475 -#define _MONITOR_JUMP_BACKWARD 476 -#define _MONITOR_RESUME 477 +#define _MAYBE_EXPAND_METHOD 474 +#define _MAYBE_EXPAND_METHOD_KW 475 +#define _MONITOR_CALL 476 +#define _MONITOR_CALL_KW 477 +#define _MONITOR_JUMP_BACKWARD 478 +#define _MONITOR_RESUME 479 #define _NOP NOP #define _POP_EXCEPT POP_EXCEPT -#define _POP_JUMP_IF_FALSE 478 -#define _POP_JUMP_IF_TRUE 479 +#define _POP_JUMP_IF_FALSE 480 +#define _POP_JUMP_IF_TRUE 481 #define _POP_TOP POP_TOP -#define _POP_TOP_LOAD_CONST_INLINE 480 -#define _POP_TOP_LOAD_CONST_INLINE_BORROW 481 -#define _POP_TWO_LOAD_CONST_INLINE_BORROW 482 +#define _POP_TOP_LOAD_CONST_INLINE 482 +#define _POP_TOP_LOAD_CONST_INLINE_BORROW 483 +#define _POP_TWO_LOAD_CONST_INLINE_BORROW 484 #define _PUSH_EXC_INFO PUSH_EXC_INFO -#define _PUSH_FRAME 483 +#define _PUSH_FRAME 485 #define _PUSH_NULL PUSH_NULL -#define _PUSH_NULL_CONDITIONAL 484 -#define _PY_FRAME_GENERAL 485 -#define _PY_FRAME_KW 486 -#define _QUICKEN_RESUME 487 -#define _REPLACE_WITH_TRUE 488 +#define _PUSH_NULL_CONDITIONAL 486 +#define _PY_FRAME_GENERAL 487 +#define _PY_FRAME_KW 488 +#define _QUICKEN_RESUME 489 +#define _REPLACE_WITH_TRUE 490 #define _RESUME_CHECK RESUME_CHECK #define _RETURN_GENERATOR RETURN_GENERATOR #define _RETURN_VALUE RETURN_VALUE -#define _SAVE_RETURN_OFFSET 489 -#define _SEND 490 -#define _SEND_GEN_FRAME 491 +#define _SAVE_RETURN_OFFSET 491 +#define _SEND 492 +#define _SEND_GEN_FRAME 493 #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 492 -#define _STORE_ATTR 493 -#define _STORE_ATTR_INSTANCE_VALUE 494 -#define _STORE_ATTR_SLOT 495 -#define _STORE_ATTR_WITH_HINT 496 +#define _START_EXECUTOR 494 +#define _STORE_ATTR 495 +#define _STORE_ATTR_INSTANCE_VALUE 496 +#define _STORE_ATTR_SLOT 497 +#define _STORE_ATTR_WITH_HINT 498 #define _STORE_DEREF STORE_DEREF -#define _STORE_FAST 497 -#define _STORE_FAST_0 498 -#define _STORE_FAST_1 499 -#define _STORE_FAST_2 500 -#define _STORE_FAST_3 501 -#define _STORE_FAST_4 502 -#define _STORE_FAST_5 503 -#define _STORE_FAST_6 504 -#define _STORE_FAST_7 505 +#define _STORE_FAST 499 +#define _STORE_FAST_0 500 +#define _STORE_FAST_1 501 +#define _STORE_FAST_2 502 +#define _STORE_FAST_3 503 +#define _STORE_FAST_4 504 +#define _STORE_FAST_5 505 +#define _STORE_FAST_6 506 +#define _STORE_FAST_7 507 #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 506 -#define _STORE_SUBSCR 507 -#define _STORE_SUBSCR_DICT 508 -#define _STORE_SUBSCR_LIST_INT 509 +#define _STORE_SLICE 508 +#define _STORE_SUBSCR 509 +#define _STORE_SUBSCR_DICT 510 +#define _STORE_SUBSCR_LIST_INT 511 #define _SWAP SWAP -#define _TIER2_RESUME_CHECK 510 -#define _TO_BOOL 511 +#define _TIER2_RESUME_CHECK 512 +#define _TO_BOOL 513 #define _TO_BOOL_BOOL TO_BOOL_BOOL #define _TO_BOOL_INT TO_BOOL_INT -#define _TO_BOOL_LIST 512 +#define _TO_BOOL_LIST 514 #define _TO_BOOL_NONE TO_BOOL_NONE -#define _TO_BOOL_STR 513 +#define _TO_BOOL_STR 515 #define _UNARY_INVERT UNARY_INVERT #define _UNARY_NEGATIVE UNARY_NEGATIVE #define _UNARY_NOT UNARY_NOT #define _UNPACK_EX UNPACK_EX -#define _UNPACK_SEQUENCE 514 -#define _UNPACK_SEQUENCE_LIST 515 -#define _UNPACK_SEQUENCE_TUPLE 516 -#define _UNPACK_SEQUENCE_TWO_TUPLE 517 +#define _UNPACK_SEQUENCE 516 +#define _UNPACK_SEQUENCE_LIST 517 +#define _UNPACK_SEQUENCE_TUPLE 518 +#define _UNPACK_SEQUENCE_TWO_TUPLE 519 #define _WITH_EXCEPT_START WITH_EXCEPT_START #define _YIELD_VALUE YIELD_VALUE -#define MAX_UOP_ID 517 +#define MAX_UOP_ID 519 #ifdef __cplusplus } diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index 734b9636bb9f14..ee621f2dd08b38 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -890,42 +890,26 @@ dummy_func(void) { } } - op(_CALL_ISINSTANCE, (callable, self_or_null, args[oparg] -- res)) { - if (sym_is_null(self_or_null) || sym_is_not_null(self_or_null)) { - if (sym_is_not_null(self_or_null)) { - args--; - } - JitOptSymbol *cls_sym = args[1]; - JitOptSymbol *inst_sym = args[0]; - - if(sym_is_const(ctx, cls_sym) && sym_matches_type(cls_sym, &PyType_Type)) { - // isinstance(obj, cls) where cls is a known class - PyTypeObject *cls = (PyTypeObject *)sym_get_const(ctx, cls_sym); - - if (sym_has_type(inst_sym)) { - // isinstance(obj, cls) where both obj and cls have known types - // We can deduce either True or False - PyTypeObject *inst_type = sym_get_type(inst_sym); - // The below check is equivalent to PyObject_TypeCheck(inst, cls) - if (sym_matches_type(inst_sym, cls) || PyType_IsSubtype(inst_type, cls)) { - res = sym_new_const(ctx, Py_True); - } - else { - res = sym_new_const(ctx, Py_False); - } + op(_CALL_ISINSTANCE, (callable, null, instance, cls -- res)) { + // the result is always a bool, but sometimes we can + // narrow it down to True or False + res = sym_new_type(ctx, &PyBool_Type); + PyTypeObject *cls_o = (PyTypeObject *)sym_get_const(ctx, cls); + if (cls_o && sym_matches_type(cls, &PyType_Type)) { + // isinstance(obj, cls) where cls is a known class + PyTypeObject *inst_type = sym_get_type(instance); + if (inst_type) { + // isinstance(obj, cls) where both obj and cls have + // known types meaning we can deduce either True or False + + // The below check is equivalent to PyObject_TypeCheck(inst, cls) + if (sym_matches_type(instance, cls_o) || PyType_IsSubtype(inst_type, cls_o)) { + sym_set_const(res, Py_True); } else { - // isinstance(obj, cls) where obj has unknown type - res = sym_new_type(ctx, &PyBool_Type); + sym_set_const(res, Py_False); } } - else { - // isinstance(obj, cls) where cls has unknown type - res = sym_new_type(ctx, &PyBool_Type); - } - } - else { - res = sym_new_type(ctx, &PyBool_Type); } } diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index 9613e24da50c7a..b7a7169733db6e 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -2124,10 +2124,24 @@ } case _CALL_ISINSTANCE: { - JitOptSymbol **args; - JitOptSymbol *self_or_null; + JitOptSymbol *cls; + JitOptSymbol *instance; JitOptSymbol *res; - res = sym_new_not_null(ctx); + cls = stack_pointer[-1]; + instance = stack_pointer[-2]; + res = sym_new_type(ctx, &PyBool_Type); + PyTypeObject *cls_o = (PyTypeObject *)sym_get_const(ctx, cls); + if (cls_o && sym_matches_type(cls, &PyType_Type)) { + PyTypeObject *inst_type = sym_get_type(instance); + if (inst_type) { + if (sym_matches_type(instance, cls_o) || PyType_IsSubtype(inst_type, cls_o)) { + sym_set_const(res, Py_True); + } + else { + sym_set_const(res, Py_False); + } + } + } stack_pointer[-4] = res; stack_pointer += -3; assert(WITHIN_STACK_BOUNDS()); From 38370a3f6acbbeb2a074d1e59f42fef0bc3d7d07 Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Fri, 9 May 2025 00:00:48 +0200 Subject: [PATCH 07/13] Add a metaclass test --- Lib/test/test_capi/test_opt.py | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py index 6ca24b34476ef6..3d956b2c8b7027 100644 --- a/Lib/test/test_capi/test_opt.py +++ b/Lib/test/test_capi/test_opt.py @@ -2053,6 +2053,31 @@ def testfunc(n): self.assertNotIn("_TO_BOOL_BOOL", uops) self.assertIn("_GUARD_IS_TRUE_POP", uops) + def test_call_isinstance_metaclass(self): + class EvenNumberMeta(type): + def __instancecheck__(self, number): + return number % 2 == 0 + + class EvenNumber(metaclass=EvenNumberMeta): + pass + + def testfunc(n): + x = 0 + for _ in range(n): + # Only narrowed to bool + y = isinstance(42, EvenNumber) + if y: + x += 1 + return x + + res, ex = self._run_with_optimizer(testfunc, TIER2_THRESHOLD) + self.assertEqual(res, TIER2_THRESHOLD) + self.assertIsNotNone(ex) + uops = get_opnames(ex) + self.assertIn("_CALL_ISINSTANCE", uops) + self.assertNotIn("_TO_BOOL_BOOL", uops) + self.assertIn("_GUARD_IS_TRUE_POP", uops) + def global_identity(x): return x From bb228ebba407a235b5990b83e8f6a08633f6beef Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Fri, 9 May 2025 00:02:04 +0200 Subject: [PATCH 08/13] Improve test --- Lib/test/test_capi/test_opt.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py index 3d956b2c8b7027..5db1f2890df3e4 100644 --- a/Lib/test/test_capi/test_opt.py +++ b/Lib/test/test_capi/test_opt.py @@ -2012,15 +2012,11 @@ def testfunc(n): def test_call_isinstance_unknown_object(self): def testfunc(n): - class Foo: - bar = 42 - x = 0 for _ in range(n): - # we only know bar (LOAD_ATTR) is not null (set via sym_new_not_null) - bar = Foo.bar - # This will only narrow to bool and not to True due to 'bar' having - # unknown (non-null) type + # The optimizer doesn't know the return type here: + bar = eval("42") + # This will only narrow to bool: y = isinstance(bar, int) if y: x += 1 From 0ede9f37d4102c451a92a55048f3b8b3eb57880a Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Fri, 9 May 2025 20:48:58 +0200 Subject: [PATCH 09/13] Update comment --- Lib/test/test_capi/test_opt.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/test/test_capi/test_opt.py b/Lib/test/test_capi/test_opt.py index 5db1f2890df3e4..73ce55400adcdf 100644 --- a/Lib/test/test_capi/test_opt.py +++ b/Lib/test/test_capi/test_opt.py @@ -2034,8 +2034,8 @@ def test_call_isinstance_tuple_of_classes(self): def testfunc(n): x = 0 for _ in range(n): - # The optimization currently only narrows to bool - # when the second argument is a tuple of classes. + # A tuple of classes is currently not optimized, + # so this is only narrowed to bool: y = isinstance(42, (int, str)) if y: x += 1 From 3d0df4ca9af1eddbf6b9aac73d76f70015bc5222 Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Fri, 9 May 2025 20:51:21 +0200 Subject: [PATCH 10/13] Mark some stackrefs as unused --- Python/optimizer_bytecodes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index ee621f2dd08b38..537aabd073b9a6 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -890,7 +890,7 @@ dummy_func(void) { } } - op(_CALL_ISINSTANCE, (callable, null, instance, cls -- res)) { + op(_CALL_ISINSTANCE, (unused, unused, instance, cls -- res)) { // the result is always a bool, but sometimes we can // narrow it down to True or False res = sym_new_type(ctx, &PyBool_Type); From ce0cd386d87ef073c49e048bd75f33f66d6ed80a Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Fri, 9 May 2025 20:56:50 +0200 Subject: [PATCH 11/13] Simplify even more --- Python/optimizer_bytecodes.c | 25 +++++++++++-------------- Python/optimizer_cases.c.h | 16 +++++++--------- 2 files changed, 18 insertions(+), 23 deletions(-) diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index 537aabd073b9a6..2575542ec5347b 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -894,21 +894,18 @@ dummy_func(void) { // the result is always a bool, but sometimes we can // narrow it down to True or False res = sym_new_type(ctx, &PyBool_Type); + PyTypeObject *inst_type = sym_get_type(instance); PyTypeObject *cls_o = (PyTypeObject *)sym_get_const(ctx, cls); - if (cls_o && sym_matches_type(cls, &PyType_Type)) { - // isinstance(obj, cls) where cls is a known class - PyTypeObject *inst_type = sym_get_type(instance); - if (inst_type) { - // isinstance(obj, cls) where both obj and cls have - // known types meaning we can deduce either True or False - - // The below check is equivalent to PyObject_TypeCheck(inst, cls) - if (sym_matches_type(instance, cls_o) || PyType_IsSubtype(inst_type, cls_o)) { - sym_set_const(res, Py_True); - } - else { - sym_set_const(res, Py_False); - } + if (inst_type && cls_o && sym_matches_type(cls, &PyType_Type)) { + // isinstance(inst, cls) where both inst and cls have + // known types, meaning we can deduce either True or False + + // The below check is equivalent to PyObject_TypeCheck(inst, cls) + if (sym_matches_type(instance, cls_o) || PyType_IsSubtype(inst_type, cls_o)) { + sym_set_const(res, Py_True); + } + else { + sym_set_const(res, Py_False); } } } diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index b7a7169733db6e..164fb5119c40fb 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -2130,16 +2130,14 @@ cls = stack_pointer[-1]; instance = stack_pointer[-2]; res = sym_new_type(ctx, &PyBool_Type); + PyTypeObject *inst_type = sym_get_type(instance); PyTypeObject *cls_o = (PyTypeObject *)sym_get_const(ctx, cls); - if (cls_o && sym_matches_type(cls, &PyType_Type)) { - PyTypeObject *inst_type = sym_get_type(instance); - if (inst_type) { - if (sym_matches_type(instance, cls_o) || PyType_IsSubtype(inst_type, cls_o)) { - sym_set_const(res, Py_True); - } - else { - sym_set_const(res, Py_False); - } + if (inst_type && cls_o && sym_matches_type(cls, &PyType_Type)) { + if (sym_matches_type(instance, cls_o) || PyType_IsSubtype(inst_type, cls_o)) { + sym_set_const(res, Py_True); + } + else { + sym_set_const(res, Py_False); } } stack_pointer[-4] = res; From 20fd1855da25523eff7a2ea30f1a65ad888de360 Mon Sep 17 00:00:00 2001 From: "Tomas R." Date: Mon, 19 May 2025 15:37:09 +0200 Subject: [PATCH 12/13] Simplify code Co-authored-by: Brandt Bucher --- Python/optimizer_bytecodes.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Python/optimizer_bytecodes.c b/Python/optimizer_bytecodes.c index 2575542ec5347b..ad25c68e62aab2 100644 --- a/Python/optimizer_bytecodes.c +++ b/Python/optimizer_bytecodes.c @@ -901,7 +901,7 @@ dummy_func(void) { // known types, meaning we can deduce either True or False // The below check is equivalent to PyObject_TypeCheck(inst, cls) - if (sym_matches_type(instance, cls_o) || PyType_IsSubtype(inst_type, cls_o)) { + if (inst_type == cls_o || PyType_IsSubtype(inst_type, cls_o)) { sym_set_const(res, Py_True); } else { From f985963335762657b2168e162ff07ffb08875c22 Mon Sep 17 00:00:00 2001 From: Tomas Roun Date: Mon, 19 May 2025 16:36:22 +0200 Subject: [PATCH 13/13] make regen-cases --- Python/optimizer_cases.c.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Python/optimizer_cases.c.h b/Python/optimizer_cases.c.h index 164fb5119c40fb..5d469765203833 100644 --- a/Python/optimizer_cases.c.h +++ b/Python/optimizer_cases.c.h @@ -2133,7 +2133,7 @@ PyTypeObject *inst_type = sym_get_type(instance); PyTypeObject *cls_o = (PyTypeObject *)sym_get_const(ctx, cls); if (inst_type && cls_o && sym_matches_type(cls, &PyType_Type)) { - if (sym_matches_type(instance, cls_o) || PyType_IsSubtype(inst_type, cls_o)) { + if (inst_type == cls_o || PyType_IsSubtype(inst_type, cls_o)) { sym_set_const(res, Py_True); } else {