PageRenderTime 52ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/pypy/rlib/debug.py

https://bitbucket.org/dac_io/pypy
Python | 354 lines | 334 code | 16 blank | 4 comment | 10 complexity | 76a363403e34db94b900de8ac4f74f64 MD5 | raw file
  1. import sys, time
  2. from pypy.rpython.extregistry import ExtRegistryEntry
  3. from pypy.rlib.rarithmetic import is_valid_int
  4. def ll_assert(x, msg):
  5. """After translation to C, this becomes an RPyAssert."""
  6. assert x, msg
  7. class Entry(ExtRegistryEntry):
  8. _about_ = ll_assert
  9. def compute_result_annotation(self, s_x, s_msg):
  10. assert s_msg.is_constant(), ("ll_assert(x, msg): "
  11. "the msg must be constant")
  12. return None
  13. def specialize_call(self, hop):
  14. from pypy.rpython.lltypesystem import lltype
  15. vlist = hop.inputargs(lltype.Bool, lltype.Void)
  16. hop.exception_cannot_occur()
  17. hop.genop('debug_assert', vlist)
  18. def fatalerror(msg):
  19. # print the RPython traceback and abort with a fatal error
  20. from pypy.rpython.lltypesystem import lltype
  21. from pypy.rpython.lltypesystem.lloperation import llop
  22. llop.debug_print_traceback(lltype.Void)
  23. llop.debug_fatalerror(lltype.Void, msg)
  24. fatalerror._dont_inline_ = True
  25. fatalerror._jit_look_inside_ = False
  26. fatalerror._annenforceargs_ = [str]
  27. def fatalerror_notb(msg):
  28. # a variant of fatalerror() that doesn't print the RPython traceback
  29. from pypy.rpython.lltypesystem import lltype
  30. from pypy.rpython.lltypesystem.lloperation import llop
  31. llop.debug_fatalerror(lltype.Void, msg)
  32. fatalerror_notb._dont_inline_ = True
  33. fatalerror_notb._jit_look_inside_ = False
  34. fatalerror_notb._annenforceargs_ = [str]
  35. class DebugLog(list):
  36. def debug_print(self, *args):
  37. self.append(('debug_print',) + args)
  38. def debug_start(self, category, time=None):
  39. self.append(('debug_start', category, time))
  40. def debug_stop(self, category, time=None):
  41. for i in xrange(len(self)-1, -1, -1):
  42. if self[i][0] == 'debug_start':
  43. assert self[i][1] == category, (
  44. "nesting error: starts with %r but stops with %r" %
  45. (self[i][1], category))
  46. starttime = self[i][2]
  47. if starttime is not None or time is not None:
  48. self[i:] = [(category, starttime, time, self[i+1:])]
  49. else:
  50. self[i:] = [(category, self[i+1:])]
  51. return
  52. assert False, ("nesting error: no start corresponding to stop %r" %
  53. (category,))
  54. def __repr__(self):
  55. import pprint
  56. return pprint.pformat(list(self))
  57. _log = None # patched from tests to be an object of class DebugLog
  58. # or compatible
  59. def debug_print(*args):
  60. for arg in args:
  61. print >> sys.stderr, arg,
  62. print >> sys.stderr
  63. if _log is not None:
  64. _log.debug_print(*args)
  65. class Entry(ExtRegistryEntry):
  66. _about_ = debug_print
  67. def compute_result_annotation(self, *args_s):
  68. return None
  69. def specialize_call(self, hop):
  70. vlist = hop.inputargs(*hop.args_r)
  71. hop.exception_cannot_occur()
  72. t = hop.rtyper.annotator.translator
  73. if t.config.translation.log:
  74. hop.genop('debug_print', vlist)
  75. if sys.stderr.isatty():
  76. _start_colors_1 = "\033[1m\033[31m"
  77. _start_colors_2 = "\033[31m"
  78. _stop_colors = "\033[0m"
  79. else:
  80. _start_colors_1 = ""
  81. _start_colors_2 = ""
  82. _stop_colors = ""
  83. def debug_start(category):
  84. c = int(time.clock() * 100)
  85. print >> sys.stderr, '%s[%x] {%s%s' % (_start_colors_1, c,
  86. category, _stop_colors)
  87. if _log is not None:
  88. _log.debug_start(category)
  89. def debug_stop(category):
  90. c = int(time.clock() * 100)
  91. print >> sys.stderr, '%s[%x] %s}%s' % (_start_colors_2, c,
  92. category, _stop_colors)
  93. if _log is not None:
  94. _log.debug_stop(category)
  95. class Entry(ExtRegistryEntry):
  96. _about_ = debug_start, debug_stop
  97. def compute_result_annotation(self, s_category):
  98. return None
  99. def specialize_call(self, hop):
  100. fn = self.instance
  101. string_repr = hop.rtyper.type_system.rstr.string_repr
  102. vlist = hop.inputargs(string_repr)
  103. hop.exception_cannot_occur()
  104. t = hop.rtyper.annotator.translator
  105. if t.config.translation.log:
  106. hop.genop(fn.__name__, vlist)
  107. def have_debug_prints():
  108. # returns True if the next calls to debug_print show up,
  109. # and False if they would not have any effect.
  110. return True
  111. class Entry(ExtRegistryEntry):
  112. _about_ = have_debug_prints
  113. def compute_result_annotation(self):
  114. from pypy.annotation import model as annmodel
  115. t = self.bookkeeper.annotator.translator
  116. if t.config.translation.log:
  117. return annmodel.s_Bool
  118. else:
  119. return self.bookkeeper.immutablevalue(False)
  120. def specialize_call(self, hop):
  121. from pypy.rpython.lltypesystem import lltype
  122. t = hop.rtyper.annotator.translator
  123. hop.exception_cannot_occur()
  124. if t.config.translation.log:
  125. return hop.genop('have_debug_prints', [], resulttype=lltype.Bool)
  126. else:
  127. return hop.inputconst(lltype.Bool, False)
  128. def debug_offset():
  129. """ Return an offset in log file
  130. """
  131. return -1
  132. class Entry(ExtRegistryEntry):
  133. _about_ = debug_offset
  134. def compute_result_annotation(self):
  135. from pypy.annotation import model as annmodel
  136. return annmodel.SomeInteger()
  137. def specialize_call(self, hop):
  138. from pypy.rpython.lltypesystem import lltype
  139. hop.exception_cannot_occur()
  140. return hop.genop('debug_offset', [], resulttype=lltype.Signed)
  141. def debug_flush():
  142. """ Flushes the debug file
  143. """
  144. pass
  145. class Entry(ExtRegistryEntry):
  146. _about_ = debug_flush
  147. def compute_result_annotation(self):
  148. return None
  149. def specialize_call(self, hop):
  150. hop.exception_cannot_occur()
  151. return hop.genop('debug_flush', [])
  152. def llinterpcall(RESTYPE, pythonfunction, *args):
  153. """When running on the llinterp, this causes the llinterp to call to
  154. the provided Python function with the run-time value of the given args.
  155. The Python function should return a low-level object of type RESTYPE.
  156. This should never be called after translation: use this only if
  157. running_on_llinterp is true.
  158. """
  159. raise NotImplementedError
  160. class Entry(ExtRegistryEntry):
  161. _about_ = llinterpcall
  162. def compute_result_annotation(self, s_RESTYPE, s_pythonfunction, *args_s):
  163. from pypy.annotation import model as annmodel
  164. from pypy.rpython.lltypesystem import lltype
  165. assert s_RESTYPE.is_constant()
  166. assert s_pythonfunction.is_constant()
  167. s_result = s_RESTYPE.const
  168. if isinstance(s_result, lltype.LowLevelType):
  169. s_result = annmodel.lltype_to_annotation(s_result)
  170. assert isinstance(s_result, annmodel.SomeObject)
  171. return s_result
  172. def specialize_call(self, hop):
  173. from pypy.annotation import model as annmodel
  174. from pypy.rpython.lltypesystem import lltype
  175. RESTYPE = hop.args_s[0].const
  176. if not isinstance(RESTYPE, lltype.LowLevelType):
  177. assert isinstance(RESTYPE, annmodel.SomeObject)
  178. r_result = hop.rtyper.getrepr(RESTYPE)
  179. RESTYPE = r_result.lowleveltype
  180. pythonfunction = hop.args_s[1].const
  181. c_pythonfunction = hop.inputconst(lltype.Void, pythonfunction)
  182. args_v = [hop.inputarg(hop.args_r[i], arg=i)
  183. for i in range(2, hop.nb_args)]
  184. hop.exception_is_here()
  185. return hop.genop('debug_llinterpcall', [c_pythonfunction] + args_v,
  186. resulttype=RESTYPE)
  187. def check_annotation(arg, checker):
  188. """ Function checking if annotation is as expected when translating,
  189. does nothing when just run. Checker is supposed to be a constant
  190. callable which checks if annotation is as expected,
  191. arguments passed are (current annotation, bookkeeper)
  192. """
  193. return arg
  194. class Entry(ExtRegistryEntry):
  195. _about_ = check_annotation
  196. def compute_result_annotation(self, s_arg, s_checker):
  197. if not s_checker.is_constant():
  198. raise ValueError("Second argument of check_annotation must be constant")
  199. checker = s_checker.const
  200. checker(s_arg, self.bookkeeper)
  201. return s_arg
  202. def specialize_call(self, hop):
  203. hop.exception_cannot_occur()
  204. return hop.inputarg(hop.args_r[0], arg=0)
  205. def make_sure_not_resized(arg):
  206. """ Function checking whether annotation of SomeList is never resized,
  207. useful for debugging. Does nothing when run directly
  208. """
  209. return arg
  210. class Entry(ExtRegistryEntry):
  211. _about_ = make_sure_not_resized
  212. def compute_result_annotation(self, s_arg):
  213. from pypy.annotation.model import SomeList
  214. assert isinstance(s_arg, SomeList)
  215. # the logic behind it is that we try not to propagate
  216. # make_sure_not_resized, when list comprehension is not on
  217. if self.bookkeeper.annotator.translator.config.translation.list_comprehension_operations:
  218. s_arg.listdef.never_resize()
  219. else:
  220. from pypy.annotation.annrpython import log
  221. log.WARNING('make_sure_not_resized called, but has no effect since list_comprehension is off')
  222. return s_arg
  223. def specialize_call(self, hop):
  224. hop.exception_cannot_occur()
  225. return hop.inputarg(hop.args_r[0], arg=0)
  226. def mark_dict_non_null(d):
  227. """ Mark dictionary as having non-null keys and values. A warning would
  228. be emitted (not an error!) in case annotation disagrees.
  229. """
  230. assert isinstance(d, dict)
  231. return d
  232. class DictMarkEntry(ExtRegistryEntry):
  233. _about_ = mark_dict_non_null
  234. def compute_result_annotation(self, s_dict):
  235. from pypy.annotation.model import SomeDict, s_None
  236. assert isinstance(s_dict, SomeDict)
  237. s_dict.dictdef.force_non_null = True
  238. return s_dict
  239. def specialize_call(self, hop):
  240. hop.exception_cannot_occur()
  241. return hop.inputarg(hop.args_r[0], arg=0)
  242. class IntegerCanBeNegative(Exception):
  243. pass
  244. class UnexpectedRUInt(Exception):
  245. pass
  246. class ExpectedRegularInt(Exception):
  247. pass
  248. def check_nonneg(x):
  249. """Give a translation-time error if 'x' is not known to be non-negative.
  250. To help debugging, this also gives a translation-time error if 'x' is
  251. actually typed as an r_uint (in which case the call to check_nonneg()
  252. is a bit strange and probably unexpected).
  253. """
  254. assert type(x)(-1) < 0 # otherwise, 'x' is a r_uint or similar
  255. assert x >= 0
  256. return x
  257. class Entry(ExtRegistryEntry):
  258. _about_ = check_nonneg
  259. def compute_result_annotation(self, s_arg):
  260. from pypy.annotation.model import SomeInteger
  261. if isinstance(s_arg, SomeInteger) and s_arg.unsigned:
  262. raise UnexpectedRUInt("check_nonneg() arg is a %s" % (
  263. s_arg.knowntype,))
  264. s_nonneg = SomeInteger(nonneg=True)
  265. if not s_nonneg.contains(s_arg):
  266. raise IntegerCanBeNegative
  267. return s_arg
  268. def specialize_call(self, hop):
  269. hop.exception_cannot_occur()
  270. return hop.inputarg(hop.args_r[0], arg=0)
  271. def check_regular_int(x):
  272. """Give a translation-time error if 'x' is not a plain int
  273. (e.g. if it's a r_longlong or an r_uint).
  274. """
  275. assert is_valid_int(x)
  276. return x
  277. class Entry(ExtRegistryEntry):
  278. _about_ = check_regular_int
  279. def compute_result_annotation(self, s_arg):
  280. from pypy.annotation.model import SomeInteger
  281. if not SomeInteger().contains(s_arg):
  282. raise ExpectedRegularInt(s_arg)
  283. return s_arg
  284. def specialize_call(self, hop):
  285. hop.exception_cannot_occur()
  286. return hop.inputarg(hop.args_r[0], arg=0)