| 51 | |
| 52 | # Find out maximum stack usage for a function |
| 53 | def calcmaxstack(info, funcs): |
| 54 | if info.max_stack_usage is not None: |
| 55 | return |
| 56 | info.max_stack_usage = max_stack_usage = info.basic_stack_usage |
| 57 | info.max_yield_usage = max_yield_usage = info.yield_usage |
| 58 | total_calls = 0 |
| 59 | seenbefore = {} |
| 60 | # Find max of all nested calls. |
| 61 | for insnaddr, calladdr, usage in info.called_funcs: |
| 62 | callinfo = funcs.get(calladdr) |
| 63 | if callinfo is None: |
| 64 | continue |
| 65 | calcmaxstack(callinfo, funcs) |
| 66 | if callinfo.funcname not in seenbefore: |
| 67 | seenbefore[callinfo.funcname] = 1 |
| 68 | total_calls += callinfo.total_calls + 1 |
| 69 | funcnameroot = callinfo.funcname.split('.')[0] |
| 70 | if funcnameroot in IGNORE: |
| 71 | # This called function is ignored - don't contribute it to |
| 72 | # the max stack. |
| 73 | continue |
| 74 | totusage = usage + callinfo.max_stack_usage |
| 75 | totyieldusage = usage + callinfo.max_yield_usage |
| 76 | if funcnameroot in STACKHOP: |
| 77 | # Don't count children of this function |
| 78 | totusage = totyieldusage = usage |
| 79 | if totusage > max_stack_usage: |
| 80 | max_stack_usage = totusage |
| 81 | if callinfo.max_yield_usage >= 0 and totyieldusage > max_yield_usage: |
| 82 | max_yield_usage = totyieldusage |
| 83 | info.max_stack_usage = max_stack_usage |
| 84 | info.max_yield_usage = max_yield_usage |
| 85 | info.total_calls = total_calls |
| 86 | |
| 87 | # Try to arrange output so that functions that call each other are |
| 88 | # near each other. |