PageRenderTime 42ms CodeModel.GetById 12ms RepoModel.GetById 0ms app.codeStats 0ms

/pypy/rlib/debug.py

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