Maratyszcza / Maratyszcza/PeachPy

'maximum recursion depth exceeded' while finalizing a large function

Open
#74 1 comment 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Python
Stars
2.1k
Forks
170
PR merge metrics
No merged PRs in 30d

Description

I'm generating a fairly large function using PeachPy (compiling from another language). When the function has a large number of labels it seems that the finalization invoked when `RETURN` is called is blowing the Python style.

Part of the stack trace:

```
File "function.py", line 549, in analyze_reachability
output_block.analyze_reachability()
File "function.py", line 549, in analyze_reachability
output_block.analyze_reachability()
File "function.py", line 549, in analyze_reachability
output_block.analyze_reachability()
File "function.py", line 549, in analyze_reachability
output_block.analyze_reachability()
```

FWIW I'm not even using the register allocation features, all my registers are managed manually. A silly reproducer below:

```
import peachpy
import peachpy.x86_64

x = peachpy.Argument(peachpy.int64_t)
y = peachpy.Argument(peachpy.int64_t)

with peachpy.x86_64.Function("Times", (x, y), peachpy.int64_t) as asm_function:
reg_x = peachpy.x86_64.rax
reg_y = peachpy.x86_64.rbx
reg_accum = peachpy.x86_64.rcx

peachpy.x86_64.LOAD.ARGUMENT(reg_x, x)
peachpy.x86_64.LOAD.ARGUMENT(reg_y, y)
peachpy.x86_64.MOV(reg_accum, 0)

for i in range(1000):
loop_start_label = peachpy.x86_64.Label('loop_start{}'.format(i))
loop_end_label = peachpy.x86_64.Label('loop_end{}'.format(i))

peachpy.x86_64.CMP(reg_y, 0)
peachpy.x86_64.JE(loop_end_label)
peachpy.x86_64.LABEL(loop_start_label) # bind the label
peachpy.x86_64.ADD(reg_accum, reg_x)
peachpy.x86_64.SUB(reg_y, 1)
peachpy.x86_64.JG(loop_start_label)
peachpy.x86_64.LABEL(loop_end_label) # bind the label

peachpy.x86_64.RETURN(reg_accum)

abi = peachpy.x86_64.abi.detect()
encoded_function = asm_function.finalize(abi).encode()
python_function = encoded_function.load()

print(encoded_function.format())
code = python_function.code_segment

fname = '/tmp/ppout.bin'
with open(fname, 'wb') as f:
f.write(code)

print('Wrote code to file [{0}]: {1}'.format(fname, code))

# The JIT call
print(python_function(3, 4))
```

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in function.py at analyze_reachability, shown repeatedly in the recursion traceback, and follow how RETURN triggers finalization. Run the supplied 1,000-label reproducer through asm_function.finalize(abi).encode(). Done means the large function finalizes and encodes without exceeding Python's recursion depth.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
compilers
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Clearly specified
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.