GeezerVisonThe World Wide Web, restored to 800 pixels of glory. |
| Home|About|Gaming cabinet|Archives|How it works|Starter sites |
GeezerVison is showing github.com — CALL_EX_PY and CALL_KW_BOUND_METHOD can bypass RecursionError after specialization · Issue #155151 · python/cpython Open Labels interpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)type-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error DescriptionBug descriptionWhile verifying whether CPython's specialized opcodes preserve the behavior of their corresponding generic opcodes, I found an unexpected difference at the Python recursion limit. The verification initially identified states in which For the same Python call and arguments:
ReproducerSave the following as import dis import os import sys ARGS = () hits = 0 claimed = False def ex_target(): global hits hits += 1 return 42 class Receiver: def target(self, *, value): global hits hits += 1 return value BOUND_TARGET = Receiver().target def call_ex_probe(warm): global claimed while not warm: try: return call_ex_probe(False) except RecursionError: # Only the deepest active frame attempts the target call. # Outer frames propagate RecursionError instead of retrying # after one frame has unwound. if claimed: raise claimed = True warm = True # Warmup and recursion-boundary execution use this exact call site. return ex_target(*ARGS) def call_kw_bound_method_probe(warm): global claimed while not warm: try: return call_kw_bound_method_probe(False) except RecursionError: if claimed: raise claimed = True warm = True return BOUND_TARGET(value=43) case = os.environ["REPRO_CASE"] mode = os.environ["REPRO_MODE"] if case == "call-ex": probe = call_ex_probe interesting_opcodes = {"CALL_FUNCTION_EX", "CALL_EX_PY"} else: probe = call_kw_bound_method_probe interesting_opcodes = {"CALL_KW", "CALL_KW_BOUND_METHOD"} if mode == "specialized": for _ in range(100): probe(True) opcodes = [ instruction.opname for instruction in dis.get_instructions(probe, adaptive=True) if instruction.opname in interesting_opcodes ] print("case:", case) print("mode:", mode) print("opcode:", opcodes) hits_before = hits sys.setrecursionlimit(200) try: print("result:", probe(False)) except RecursionError: print("result: RecursionError") print("target executions at boundary:", hits - hits_before) Run each case in a fresh process: $ REPRO_CASE=call-ex REPRO_MODE=control ./python repro.py case: call-ex mode: control opcode: ['CALL_FUNCTION_EX'] result: RecursionError target executions at boundary: 0 $ REPRO_CASE=call-ex REPRO_MODE=specialized ./python repro.py case: call-ex mode: specialized opcode: ['CALL_EX_PY'] result: 42 target executions at boundary: 1 $ REPRO_CASE=call-kw-bound-method REPRO_MODE=control ./python repro.py case: call-kw-bound-method mode: control opcode: ['CALL_KW'] result: RecursionError target executions at boundary: 0 $ REPRO_CASE=call-kw-bound-method REPRO_MODE=specialized ./python repro.py case: call-kw-bound-method mode: specialized opcode: ['CALL_KW_BOUND_METHOD'] result: 43 target executions at boundary: 1 The target functions and arguments are unchanged between control and specialized runs. Expected behaviorThe generic and specialized opcodes should have the same observable behavior. Given the current generic behavior, the specialized opcode should either deoptimize or raise Suspected cause and source locationsAI assistance disclosure: The suspected-cause analysis and source-location summary in this section were prepared with assistance from OpenAI Codex using the GPT-5.6-sol model. Generic inlined frame entry reaches
The specialized paths instead end in CPython defines
However, Likewise, The generic The same two missing guards are still visible in CPython main at commit A possible fix may be to add Verification contextThis was initially found while checking conditional contextual refinement between generic and specialized opcodes. The formal counterexample occurs when The runtime reproducer above confirms the corresponding observable difference. EnvironmentI inspected the cited CPython main commit for the missing guards, but I have not yet executed the reproducer on a main-branch build. CPython versions tested on:3.15 Operating systems tested on:Linux Linked PRsActivity
MetadataMetadataAssigneesLabelsinterpreter-core(Objects, Python, Grammar, and Parser dirs)(Objects, Python, Grammar, and Parser dirs)type-bugAn unexpected behavior, bug, or errorAn unexpected behavior, bug, or error ProjectsMilestoneRelationshipsDevelopmentIssue actions |
| You are visitor 01402503 — GeezerVison does not store the pages you look up. Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required. |