(op: parser.CodeDef)
| 949 | |
| 950 | |
| 951 | def compute_properties(op: parser.CodeDef) -> Properties: |
| 952 | escaping_calls = find_escaping_api_calls(op) |
| 953 | has_free = ( |
| 954 | variable_used(op, "PyCell_New") |
| 955 | or variable_used(op, "PyCell_GetRef") |
| 956 | or variable_used(op, "PyCell_SetTakeRef") |
| 957 | or variable_used(op, "PyCell_SwapTakeRef") |
| 958 | ) |
| 959 | deopts_if = variable_used(op, "DEOPT_IF") |
| 960 | exits_if = variable_used(op, "EXIT_IF") |
| 961 | exit_if_at_end = variable_used(op, "AT_END_EXIT_IF") |
| 962 | deopts_periodic = variable_used(op, "HANDLE_PENDING_AND_DEOPT_IF") |
| 963 | exits_and_deopts = sum((deopts_if, exits_if, deopts_periodic)) |
| 964 | if exits_and_deopts > 1: |
| 965 | tkn = op.tokens[0] |
| 966 | raise lexer.make_syntax_error( |
| 967 | "Op cannot contain more than one of EXIT_IF, DEOPT_IF and HANDLE_PENDING_AND_DEOPT_IF", |
| 968 | tkn.filename, |
| 969 | tkn.line, |
| 970 | tkn.column, |
| 971 | op.name, |
| 972 | ) |
| 973 | error_with_pop = has_error_with_pop(op) |
| 974 | error_without_pop = has_error_without_pop(op) |
| 975 | escapes = stmt_escapes(op.block) |
| 976 | pure = False if isinstance(op, parser.LabelDef) else "pure" in op.annotations |
| 977 | no_save_ip = False if isinstance(op, parser.LabelDef) else "no_save_ip" in op.annotations |
| 978 | unpredictable, branches_seen = stmt_has_jump_on_unpredictable_path(op.block, 0) |
| 979 | unpredictable_jump = False if isinstance(op, parser.LabelDef) else (unpredictable and branches_seen > 0) |
| 980 | return Properties( |
| 981 | escaping_calls=escaping_calls, |
| 982 | escapes=escapes, |
| 983 | error_with_pop=error_with_pop, |
| 984 | error_without_pop=error_without_pop, |
| 985 | deopts=deopts_if, |
| 986 | deopts_periodic=deopts_periodic, |
| 987 | side_exit=exits_if, |
| 988 | side_exit_at_end=exit_if_at_end, |
| 989 | oparg=oparg_used(op), |
| 990 | jumps=variable_used(op, "JUMPBY"), |
| 991 | eval_breaker="CHECK_PERIODIC" in op.name, |
| 992 | needs_this=variable_used(op, "this_instr"), |
| 993 | always_exits=always_exits(op), |
| 994 | sync_sp=variable_used(op, "SYNC_SP"), |
| 995 | uses_co_consts=variable_used(op, "FRAME_CO_CONSTS"), |
| 996 | uses_co_names=variable_used(op, "FRAME_CO_NAMES"), |
| 997 | uses_locals=variable_used(op, "GETLOCAL") and not has_free, |
| 998 | uses_opcode=variable_used(op, "opcode"), |
| 999 | has_free=has_free, |
| 1000 | pure=pure, |
| 1001 | no_save_ip=no_save_ip, |
| 1002 | tier=tier_variable(op), |
| 1003 | needs_prev=variable_used(op, "prev_instr"), |
| 1004 | needs_guard_ip=(isinstance(op, parser.InstDef) |
| 1005 | and (unpredictable_jump and "replaced" not in op.annotations)) |
| 1006 | or variable_used(op, "LOAD_IP") |
| 1007 | or variable_used(op, "DISPATCH_INLINED"), |
| 1008 | unpredictable_jump=unpredictable_jump, |
no test coverage detected
searching dependent graphs…