1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
|
"""
Semi-public interface to gather and print a raw traceback, e.g.
from the faulthandler module.
"""
from rpython.rlib.rvmprof import cintf, rvmprof
from rpython.rlib.objectmodel import specialize
from rpython.rtyper.lltypesystem import lltype, llmemory, rffi
def traceback(estimate_number_of_entries):
"""Build and return a vmprof-like traceback, as a pair (array_p,
array_length). The caller must free array_p. Not for signal handlers:
for these, call vmprof_get_traceback() from C code.
"""
_cintf = rvmprof._get_vmprof().cintf
size = estimate_number_of_entries * 2 + 4
stack = cintf.get_rvmprof_stack()
array_p = lltype.malloc(rffi.SIGNEDP.TO, size, flavor='raw')
NULL = llmemory.NULL
array_length = _cintf.vmprof_get_traceback(stack, NULL, array_p, size)
return (array_p, array_length)
LOC_INTERPRETED = 0
LOC_JITTED = 1
LOC_JITTED_INLINED = 2
@specialize.arg(0, 1)
def _traceback_one(CodeClass, callback, arg, code_id, loc):
found_code = None
if code_id != 0:
all_code_wrefs = CodeClass._vmprof_weak_list.get_all_handles()
i = len(all_code_wrefs) - 1
while i >= 0:
code = all_code_wrefs[i]()
if code is not None and code._vmprof_unique_id == code_id:
found_code = code
break
i -= 1
callback(found_code, loc, arg)
@specialize.arg(0, 1)
def walk_traceback(CodeClass, callback, arg, array_p, array_length):
"""Invoke 'callback(code_obj, loc, arg)' for every traceback entry.
'code_obj' may be None if it can't be determined. 'loc' is one
of the LOC_xxx constants.
"""
i = 0
while i < array_length - 1:
tag = array_p[i]
tagged_value = array_p[i + 1]
if tag == rvmprof.VMPROF_CODE_TAG:
loc = LOC_INTERPRETED
_traceback_one(CodeClass, callback, arg, tagged_value, loc)
elif tag == rvmprof.VMPROF_JITTED_TAG:
if i + 2 >= array_length: # skip last entry, can't determine if
break # it's LOC_JITTED_INLINED or LOC_JITTED
if array_p[i + 2] == rvmprof.VMPROF_JITTED_TAG:
loc = LOC_JITTED_INLINED
else:
loc = LOC_JITTED
_traceback_one(CodeClass, callback, arg, tagged_value, loc)
i += 2
|