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 { pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy