PageRenderTime 60ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/rpython/rtyper/llinterp.py

https://bitbucket.org/kcr/pypy
Python | 1406 lines | 1390 code | 12 blank | 4 comment | 13 complexity | ea1fa93efd5869be2f04a00c53b5283d MD5 | raw file
Possible License(s): Apache-2.0
  1. import cStringIO
  2. import os
  3. import sys
  4. import traceback
  5. import py
  6. from rpython.flowspace.model import (FunctionGraph, Constant, Variable,
  7. c_last_exception)
  8. from rpython.rlib import rstackovf
  9. from rpython.rlib.objectmodel import (ComputedIntSymbolic, CDefinedIntSymbolic,
  10. Symbolic)
  11. # intmask is used in an exec'd code block
  12. from rpython.rlib.rarithmetic import (ovfcheck, is_valid_int, intmask,
  13. r_uint, r_longlong, r_ulonglong, r_longlonglong)
  14. from rpython.rtyper.lltypesystem import lltype, llmemory, lloperation, llheap, rclass
  15. from rpython.rtyper.ootypesystem import ootype
  16. log = py.log.Producer('llinterp')
  17. class LLException(Exception):
  18. def __init__(self, *args):
  19. "NOT_RPYTHON"
  20. Exception.__init__(self, *args)
  21. def __str__(self):
  22. etype = self.args[0]
  23. #evalue = self.args[1]
  24. if len(self.args) > 2:
  25. f = cStringIO.StringIO()
  26. original_type, original_value, original_tb = self.args[2]
  27. traceback.print_exception(original_type, original_value, original_tb,
  28. file=f)
  29. extra = '\n' + f.getvalue().rstrip('\n')
  30. extra = extra.replace('\n', '\n | ') + '\n `------'
  31. else:
  32. extra = ''
  33. return '<LLException %r%s>' % (type_name(etype), extra)
  34. class LLFatalError(Exception):
  35. def __str__(self):
  36. return ': '.join([str(x) for x in self.args])
  37. def type_name(etype):
  38. if isinstance(lltype.typeOf(etype), lltype.Ptr):
  39. return ''.join(etype.name).rstrip('\x00')
  40. else:
  41. # ootype!
  42. return etype._INSTANCE._name.split(".")[-1]
  43. class LLInterpreter(object):
  44. """ low level interpreter working with concrete values. """
  45. current_interpreter = None
  46. def __init__(self, typer, tracing=True, exc_data_ptr=None):
  47. self.bindings = {}
  48. self.typer = typer
  49. # 'heap' is module or object that provides malloc, etc for lltype ops
  50. self.heap = llheap
  51. self.exc_data_ptr = exc_data_ptr
  52. self.frame_stack = []
  53. self.tracer = None
  54. self.frame_class = LLFrame
  55. if tracing:
  56. self.tracer = Tracer()
  57. def eval_graph(self, graph, args=(), recursive=False):
  58. llframe = self.frame_class(graph, args, self)
  59. if self.tracer and not recursive:
  60. global tracer1
  61. tracer1 = self.tracer
  62. self.tracer.start()
  63. retval = None
  64. self.traceback_frames = []
  65. old_frame_stack = self.frame_stack[:]
  66. prev_interpreter = LLInterpreter.current_interpreter
  67. LLInterpreter.current_interpreter = self
  68. try:
  69. try:
  70. retval = llframe.eval()
  71. except LLException, e:
  72. log.error("LLEXCEPTION: %s" % (e, ))
  73. self.print_traceback()
  74. if self.tracer:
  75. self.tracer.dump('LLException: %s\n' % (e,))
  76. raise
  77. except Exception, e:
  78. if getattr(e, '_go_through_llinterp_uncaught_', False):
  79. raise
  80. log.error("AN ERROR OCCURED: %s" % (e, ))
  81. self.print_traceback()
  82. if self.tracer:
  83. line = str(e)
  84. if line:
  85. line = ': ' + line
  86. line = '* %s' % (e.__class__.__name__,) + line
  87. self.tracer.dump(line + '\n')
  88. raise
  89. finally:
  90. LLInterpreter.current_interpreter = prev_interpreter
  91. assert old_frame_stack == self.frame_stack
  92. if self.tracer:
  93. if retval is not None:
  94. self.tracer.dump(' ---> %r\n' % (retval,))
  95. if not recursive:
  96. self.tracer.stop()
  97. return retval
  98. def print_traceback(self):
  99. frames = self.traceback_frames
  100. frames.reverse()
  101. self.traceback_frames = []
  102. lines = []
  103. for frame in frames:
  104. logline = frame.graph.name + "()"
  105. if frame.curr_block is None:
  106. logline += " <not running yet>"
  107. lines.append(logline)
  108. continue
  109. try:
  110. logline += " " + self.typer.annotator.annotated[frame.curr_block].func.__module__
  111. except (KeyError, AttributeError, TypeError):
  112. logline += " <unknown module>"
  113. lines.append(logline)
  114. for i, operation in enumerate(frame.curr_block.operations):
  115. if i == frame.curr_operation_index:
  116. logline = "E %s"
  117. else:
  118. logline = " %s"
  119. lines.append(logline % (operation, ))
  120. if self.tracer:
  121. self.tracer.dump('Traceback\n', bold=True)
  122. for line in lines:
  123. self.tracer.dump(line + '\n')
  124. for line in lines:
  125. log.traceback(line)
  126. def find_roots(self):
  127. """Return a list of the addresses of the roots."""
  128. #log.findroots("starting")
  129. roots = []
  130. for frame in self.frame_stack:
  131. #log.findroots("graph", frame.graph.name)
  132. frame.find_roots(roots)
  133. return roots
  134. def find_exception(self, exc):
  135. assert isinstance(exc, LLException)
  136. klass, inst = exc.args[0], exc.args[1]
  137. for cls in enumerate_exceptions_top_down():
  138. if hasattr(klass, 'name'): # lltype
  139. if "".join(klass.name).rstrip("\0") == cls.__name__:
  140. return cls
  141. else: # ootype
  142. if klass._INSTANCE._name.split('.')[-1] == cls.__name__:
  143. return cls
  144. raise ValueError("couldn't match exception, maybe it"
  145. " has RPython attributes like OSError?")
  146. def get_transformed_exc_data(self, graph):
  147. if hasattr(graph, 'exceptiontransformed'):
  148. return graph.exceptiontransformed
  149. if getattr(graph, 'rgenop', False):
  150. return self.exc_data_ptr
  151. return None
  152. def _store_exception(self, exc):
  153. raise PleaseOverwriteStoreException("You just invoked ll2ctypes callback without overwriting _store_exception on llinterpreter")
  154. class PleaseOverwriteStoreException(Exception):
  155. pass
  156. def checkptr(ptr):
  157. assert isinstance(lltype.typeOf(ptr), lltype.Ptr)
  158. def checkadr(addr):
  159. assert lltype.typeOf(addr) is llmemory.Address
  160. def is_inst(inst):
  161. return isinstance(lltype.typeOf(inst), (ootype.Instance, ootype.BuiltinType, ootype.StaticMethod))
  162. def checkinst(inst):
  163. assert is_inst(inst)
  164. class LLFrame(object):
  165. def __init__(self, graph, args, llinterpreter):
  166. assert not graph or isinstance(graph, FunctionGraph)
  167. self.graph = graph
  168. self.args = args
  169. self.llinterpreter = llinterpreter
  170. self.heap = llinterpreter.heap
  171. self.bindings = {}
  172. self.curr_block = None
  173. self.curr_operation_index = 0
  174. self.alloca_objects = []
  175. def newsubframe(self, graph, args):
  176. return self.__class__(graph, args, self.llinterpreter)
  177. # _______________________________________________________
  178. # variable setters/getters helpers
  179. def clear(self):
  180. self.bindings.clear()
  181. def fillvars(self, block, values):
  182. vars = block.inputargs
  183. assert len(vars) == len(values), (
  184. "block %s received %d args, expected %d" % (
  185. block, len(values), len(vars)))
  186. for var, val in zip(vars, values):
  187. self.setvar(var, val)
  188. def setvar(self, var, val):
  189. if var.concretetype is not lltype.Void:
  190. try:
  191. val = lltype.enforce(var.concretetype, val)
  192. except TypeError:
  193. assert False, "type error: input value of type:\n\n\t%r\n\n===> variable of type:\n\n\t%r\n" % (lltype.typeOf(val), var.concretetype)
  194. assert isinstance(var, Variable)
  195. self.bindings[var] = val
  196. def setifvar(self, var, val):
  197. if isinstance(var, Variable):
  198. self.setvar(var, val)
  199. def getval(self, varorconst):
  200. try:
  201. val = varorconst.value
  202. except AttributeError:
  203. val = self.bindings[varorconst]
  204. if isinstance(val, ComputedIntSymbolic):
  205. val = val.compute_fn()
  206. if varorconst.concretetype is not lltype.Void:
  207. try:
  208. val = lltype.enforce(varorconst.concretetype, val)
  209. except TypeError:
  210. assert False, "type error: %r val from %r var/const" % (lltype.typeOf(val), varorconst.concretetype)
  211. return val
  212. def getval_or_subop(self, varorsubop):
  213. from rpython.translator.oosupport.treebuilder import SubOperation
  214. if isinstance(varorsubop, SubOperation):
  215. self.eval_operation(varorsubop.op)
  216. resultval = self.getval(varorsubop.op.result)
  217. del self.bindings[varorsubop.op.result] # XXX hack
  218. return resultval
  219. else:
  220. return self.getval(varorsubop)
  221. # _______________________________________________________
  222. # other helpers
  223. def getoperationhandler(self, opname):
  224. ophandler = getattr(self, 'op_' + opname, None)
  225. if ophandler is None:
  226. # try to import the operation from opimpl.py
  227. ophandler = lloperation.LL_OPERATIONS[opname].fold
  228. setattr(self.__class__, 'op_' + opname, staticmethod(ophandler))
  229. return ophandler
  230. # _______________________________________________________
  231. # evaling functions
  232. def eval(self):
  233. graph = self.graph
  234. tracer = self.llinterpreter.tracer
  235. if tracer:
  236. tracer.enter(graph)
  237. self.llinterpreter.frame_stack.append(self)
  238. try:
  239. try:
  240. nextblock = graph.startblock
  241. args = self.args
  242. while 1:
  243. self.clear()
  244. self.fillvars(nextblock, args)
  245. nextblock, args = self.eval_block(nextblock)
  246. if nextblock is None:
  247. for obj in self.alloca_objects:
  248. obj._obj._free()
  249. return args
  250. except Exception:
  251. self.llinterpreter.traceback_frames.append(self)
  252. raise
  253. finally:
  254. leavingframe = self.llinterpreter.frame_stack.pop()
  255. assert leavingframe is self
  256. if tracer:
  257. tracer.leave()
  258. def eval_block(self, block):
  259. """ return (nextblock, values) tuple. If nextblock
  260. is None, values is the concrete return value.
  261. """
  262. self.curr_block = block
  263. catch_exception = block.exitswitch == c_last_exception
  264. e = None
  265. try:
  266. for i, op in enumerate(block.operations):
  267. self.curr_operation_index = i
  268. self.eval_operation(op)
  269. except LLException, e:
  270. if not (catch_exception and op is block.operations[-1]):
  271. raise
  272. except RuntimeError, e:
  273. rstackovf.check_stack_overflow()
  274. # xxx fish fish fish for proper etype and evalue to use
  275. rtyper = self.llinterpreter.typer
  276. bk = rtyper.annotator.bookkeeper
  277. classdef = bk.getuniqueclassdef(rstackovf._StackOverflow)
  278. exdata = rtyper.getexceptiondata()
  279. evalue = exdata.get_standard_ll_exc_instance(rtyper, classdef)
  280. etype = exdata.fn_type_of_exc_inst(evalue)
  281. e = LLException(etype, evalue)
  282. if not (catch_exception and op is block.operations[-1]):
  283. raise e
  284. # determine nextblock and/or return value
  285. if len(block.exits) == 0:
  286. # return block
  287. tracer = self.llinterpreter.tracer
  288. if len(block.inputargs) == 2:
  289. # exception
  290. if tracer:
  291. tracer.dump('raise')
  292. etypevar, evaluevar = block.getvariables()
  293. etype = self.getval(etypevar)
  294. evalue = self.getval(evaluevar)
  295. # watch out, these are _ptr's
  296. raise LLException(etype, evalue)
  297. resultvar, = block.getvariables()
  298. result = self.getval(resultvar)
  299. exc_data = self.llinterpreter.get_transformed_exc_data(self.graph)
  300. if exc_data:
  301. # re-raise the exception set by this graph, if any
  302. etype = exc_data.exc_type
  303. if etype:
  304. evalue = exc_data.exc_value
  305. if tracer:
  306. tracer.dump('raise')
  307. exc_data.exc_type = lltype.typeOf(etype)._defl()
  308. exc_data.exc_value = lltype.typeOf(evalue)._defl()
  309. from rpython.translator import exceptiontransform
  310. T = resultvar.concretetype
  311. errvalue = exceptiontransform.error_value(T)
  312. # check that the exc-transformed graph returns the error
  313. # value when it returns with an exception set
  314. assert result == errvalue
  315. raise LLException(etype, evalue)
  316. if tracer:
  317. tracer.dump('return')
  318. return None, result
  319. elif block.exitswitch is None:
  320. # single-exit block
  321. assert len(block.exits) == 1
  322. link = block.exits[0]
  323. elif catch_exception:
  324. link = block.exits[0]
  325. if e:
  326. exdata = self.llinterpreter.typer.getexceptiondata()
  327. cls = e.args[0]
  328. inst = e.args[1]
  329. for link in block.exits[1:]:
  330. assert issubclass(link.exitcase, py.builtin.BaseException)
  331. if self.op_direct_call(exdata.fn_exception_match,
  332. cls, link.llexitcase):
  333. self.setifvar(link.last_exception, cls)
  334. self.setifvar(link.last_exc_value, inst)
  335. break
  336. else:
  337. # no handler found, pass on
  338. raise e
  339. else:
  340. llexitvalue = self.getval(block.exitswitch)
  341. if block.exits[-1].exitcase == "default":
  342. defaultexit = block.exits[-1]
  343. nondefaultexits = block.exits[:-1]
  344. assert defaultexit.llexitcase is None
  345. else:
  346. defaultexit = None
  347. nondefaultexits = block.exits
  348. for link in nondefaultexits:
  349. if link.llexitcase == llexitvalue:
  350. break # found -- the result is in 'link'
  351. else:
  352. if defaultexit is None:
  353. raise ValueError("exit case %r not found in the exit links "
  354. "of %r" % (llexitvalue, block))
  355. else:
  356. link = defaultexit
  357. return link.target, [self.getval(x) for x in link.args]
  358. def eval_operation(self, operation):
  359. tracer = self.llinterpreter.tracer
  360. if tracer:
  361. tracer.dump(str(operation))
  362. ophandler = self.getoperationhandler(operation.opname)
  363. # XXX slighly unnice but an important safety check
  364. if operation.opname == 'direct_call':
  365. assert isinstance(operation.args[0], Constant)
  366. elif operation.opname == 'indirect_call':
  367. assert isinstance(operation.args[0], Variable)
  368. if getattr(ophandler, 'specialform', False):
  369. retval = ophandler(*operation.args)
  370. else:
  371. vals = [self.getval_or_subop(x) for x in operation.args]
  372. if getattr(ophandler, 'need_result_type', False):
  373. vals.insert(0, operation.result.concretetype)
  374. try:
  375. retval = ophandler(*vals)
  376. except LLException, e:
  377. # safety check check that the operation is allowed to raise that
  378. # exception
  379. if operation.opname in lloperation.LL_OPERATIONS:
  380. canraise = lloperation.LL_OPERATIONS[operation.opname].canraise
  381. if Exception not in canraise:
  382. exc = self.llinterpreter.find_exception(e)
  383. for canraiseexc in canraise:
  384. if issubclass(exc, canraiseexc):
  385. break
  386. else:
  387. raise TypeError("the operation %s is not expected to raise %s" % (operation, exc))
  388. # for exception-transformed graphs, store the LLException
  389. # into the exc_data used by this graph
  390. exc_data = self.llinterpreter.get_transformed_exc_data(
  391. self.graph)
  392. if exc_data:
  393. etype = e.args[0]
  394. evalue = e.args[1]
  395. exc_data.exc_type = etype
  396. exc_data.exc_value = evalue
  397. from rpython.translator import exceptiontransform
  398. retval = exceptiontransform.error_value(
  399. operation.result.concretetype)
  400. else:
  401. raise
  402. self.setvar(operation.result, retval)
  403. if tracer:
  404. if retval is None:
  405. tracer.dump('\n')
  406. else:
  407. tracer.dump(' ---> %r\n' % (retval,))
  408. def make_llexception(self, exc=None):
  409. if exc is None:
  410. original = sys.exc_info()
  411. exc = original[1]
  412. # it makes no sense to convert some exception classes that
  413. # just mean something buggy crashed
  414. if isinstance(exc, (AssertionError, AttributeError,
  415. TypeError, NameError,
  416. KeyboardInterrupt, SystemExit,
  417. ImportError, SyntaxError)):
  418. raise original[0], original[1], original[2] # re-raise it
  419. # for testing the JIT (see ContinueRunningNormally) we need
  420. # to let some exceptions introduced by the JIT go through
  421. # the llinterpreter uncaught
  422. if getattr(exc, '_go_through_llinterp_uncaught_', False):
  423. raise original[0], original[1], original[2] # re-raise it
  424. extraargs = (original,)
  425. else:
  426. extraargs = ()
  427. typer = self.llinterpreter.typer
  428. exdata = typer.getexceptiondata()
  429. if isinstance(exc, OSError):
  430. self.op_direct_call(exdata.fn_raise_OSError, exc.errno)
  431. assert False, "op_direct_call above should have raised"
  432. else:
  433. evalue = exdata.get_standard_ll_exc_instance_by_class(exc.__class__)
  434. etype = self.op_direct_call(exdata.fn_type_of_exc_inst, evalue)
  435. raise LLException(etype, evalue, *extraargs)
  436. def invoke_callable_with_pyexceptions(self, fptr, *args):
  437. obj = self.llinterpreter.typer.type_system.deref(fptr)
  438. try:
  439. return obj._callable(*args)
  440. except LLException, e:
  441. raise
  442. except Exception, e:
  443. if getattr(e, '_go_through_llinterp_uncaught_', False):
  444. raise
  445. if getattr(obj, '_debugexc', False):
  446. log.ERROR('The llinterpreter got an '
  447. 'unexpected exception when calling')
  448. log.ERROR('the external function %r:' % (fptr,))
  449. log.ERROR('%s: %s' % (e.__class__.__name__, e))
  450. if self.llinterpreter.tracer:
  451. self.llinterpreter.tracer.flush()
  452. import sys
  453. from rpython.translator.tool.pdbplus import PdbPlusShow
  454. PdbPlusShow(None).post_mortem(sys.exc_info()[2])
  455. self.make_llexception()
  456. def find_roots(self, roots):
  457. #log.findroots(self.curr_block.inputargs)
  458. vars = []
  459. for v in self.curr_block.inputargs:
  460. if isinstance(v, Variable):
  461. vars.append(v)
  462. for op in self.curr_block.operations[:self.curr_operation_index]:
  463. vars.append(op.result)
  464. for v in vars:
  465. TYPE = v.concretetype
  466. if isinstance(TYPE, lltype.Ptr) and TYPE.TO._gckind == 'gc':
  467. roots.append(_address_of_local_var(self, v))
  468. # __________________________________________________________
  469. # misc LL operation implementations
  470. def op_debug_view(self, *ll_objects):
  471. from rpython.translator.tool.lltracker import track
  472. track(*ll_objects)
  473. def op_debug_assert(self, x, msg):
  474. assert x, msg
  475. def op_debug_fatalerror(self, ll_msg, ll_exc=None):
  476. msg = ''.join(ll_msg.chars)
  477. if ll_exc is None:
  478. raise LLFatalError(msg)
  479. else:
  480. ll_exc_type = lltype.cast_pointer(rclass.OBJECTPTR, ll_exc).typeptr
  481. raise LLFatalError(msg, LLException(ll_exc_type, ll_exc))
  482. def op_debug_llinterpcall(self, pythonfunction, *args_ll):
  483. try:
  484. return pythonfunction(*args_ll)
  485. except:
  486. self.make_llexception()
  487. def op_debug_start_traceback(self, *args):
  488. pass # xxx write debugging code here?
  489. def op_debug_reraise_traceback(self, *args):
  490. pass # xxx write debugging code here?
  491. def op_debug_record_traceback(self, *args):
  492. pass # xxx write debugging code here?
  493. def op_debug_print_traceback(self, *args):
  494. pass # xxx write debugging code here?
  495. def op_debug_catch_exception(self, *args):
  496. pass # xxx write debugging code here?
  497. def op_jit_marker(self, *args):
  498. pass
  499. def op_jit_record_known_class(self, *args):
  500. pass
  501. def op_get_exception_addr(self, *args):
  502. raise NotImplementedError
  503. def op_get_exc_value_addr(self, *args):
  504. raise NotImplementedError
  505. def op_instrument_count(self, ll_tag, ll_label):
  506. pass # xxx for now
  507. def op_keepalive(self, value):
  508. pass
  509. def op_hint(self, x, hints):
  510. return x
  511. def op_decode_arg(self, fname, i, name, vargs, vkwds):
  512. raise NotImplementedError("decode_arg")
  513. def op_decode_arg_def(self, fname, i, name, vargs, vkwds, default):
  514. raise NotImplementedError("decode_arg_def")
  515. def op_check_no_more_arg(self, fname, n, vargs):
  516. raise NotImplementedError("check_no_more_arg")
  517. def op_getslice(self, vargs, start, stop_should_be_None):
  518. raise NotImplementedError("getslice") # only for argument parsing
  519. def op_check_self_nonzero(self, fname, vself):
  520. raise NotImplementedError("check_self_nonzero")
  521. def op_setfield(self, obj, fieldname, fieldvalue):
  522. # obj should be pointer
  523. FIELDTYPE = getattr(lltype.typeOf(obj).TO, fieldname)
  524. if FIELDTYPE is not lltype.Void:
  525. self.heap.setfield(obj, fieldname, fieldvalue)
  526. def op_bare_setfield(self, obj, fieldname, fieldvalue):
  527. # obj should be pointer
  528. FIELDTYPE = getattr(lltype.typeOf(obj).TO, fieldname)
  529. if FIELDTYPE is not lltype.Void:
  530. setattr(obj, fieldname, fieldvalue)
  531. def op_getinteriorfield(self, obj, *offsets):
  532. checkptr(obj)
  533. ob = obj
  534. for o in offsets:
  535. if isinstance(o, str):
  536. ob = getattr(ob, o)
  537. else:
  538. ob = ob[o]
  539. assert not isinstance(ob, lltype._interior_ptr)
  540. return ob
  541. def getinneraddr(self, obj, *offsets):
  542. TYPE = lltype.typeOf(obj).TO
  543. addr = llmemory.cast_ptr_to_adr(obj)
  544. for o in offsets:
  545. if isinstance(o, str):
  546. addr += llmemory.offsetof(TYPE, o)
  547. TYPE = getattr(TYPE, o)
  548. else:
  549. addr += llmemory.itemoffsetof(TYPE, o)
  550. TYPE = TYPE.OF
  551. return addr, TYPE
  552. def op_setinteriorfield(self, obj, *fieldnamesval):
  553. offsets, fieldvalue = fieldnamesval[:-1], fieldnamesval[-1]
  554. inneraddr, FIELD = self.getinneraddr(obj, *offsets)
  555. if FIELD is not lltype.Void:
  556. self.heap.setinterior(obj, inneraddr, FIELD, fieldvalue, offsets)
  557. def op_bare_setinteriorfield(self, obj, *fieldnamesval):
  558. offsets, fieldvalue = fieldnamesval[:-1], fieldnamesval[-1]
  559. inneraddr, FIELD = self.getinneraddr(obj, *offsets)
  560. if FIELD is not lltype.Void:
  561. llheap.setinterior(obj, inneraddr, FIELD, fieldvalue)
  562. def op_getarrayitem(self, array, index):
  563. return array[index]
  564. def op_setarrayitem(self, array, index, item):
  565. # array should be a pointer
  566. ITEMTYPE = lltype.typeOf(array).TO.OF
  567. if ITEMTYPE is not lltype.Void:
  568. self.heap.setarrayitem(array, index, item)
  569. def op_bare_setarrayitem(self, array, index, item):
  570. # array should be a pointer
  571. ITEMTYPE = lltype.typeOf(array).TO.OF
  572. if ITEMTYPE is not lltype.Void:
  573. array[index] = item
  574. def perform_call(self, f, ARGS, args):
  575. fobj = self.llinterpreter.typer.type_system.deref(f)
  576. has_callable = getattr(fobj, '_callable', None) is not None
  577. if hasattr(fobj, 'graph'):
  578. graph = fobj.graph
  579. else:
  580. assert has_callable, "don't know how to execute %r" % f
  581. return self.invoke_callable_with_pyexceptions(f, *args)
  582. args_v = graph.getargs()
  583. if len(ARGS) != len(args_v):
  584. raise TypeError("graph with %d args called with wrong func ptr type: %r" %(len(args_v), ARGS))
  585. for T, v in zip(ARGS, args_v):
  586. if not lltype.isCompatibleType(T, v.concretetype):
  587. raise TypeError("graph with %r args called with wrong func ptr type: %r" %
  588. (tuple([v.concretetype for v in args_v]), ARGS))
  589. frame = self.newsubframe(graph, args)
  590. return frame.eval()
  591. def op_direct_call(self, f, *args):
  592. FTYPE = self.llinterpreter.typer.type_system.derefType(lltype.typeOf(f))
  593. return self.perform_call(f, FTYPE.ARGS, args)
  594. def op_indirect_call(self, f, *args):
  595. graphs = args[-1]
  596. args = args[:-1]
  597. if graphs is not None:
  598. obj = self.llinterpreter.typer.type_system.deref(f)
  599. if hasattr(obj, 'graph'):
  600. assert obj.graph in graphs
  601. else:
  602. pass
  603. #log.warn("op_indirect_call with graphs=None:", f)
  604. return self.op_direct_call(f, *args)
  605. def op_malloc(self, obj, flags):
  606. flavor = flags['flavor']
  607. zero = flags.get('zero', False)
  608. track_allocation = flags.get('track_allocation', True)
  609. if flavor == "stack":
  610. result = self.heap.malloc(obj, zero=zero, flavor='raw')
  611. self.alloca_objects.append(result)
  612. return result
  613. ptr = self.heap.malloc(obj, zero=zero, flavor=flavor,
  614. track_allocation=track_allocation)
  615. return ptr
  616. def op_malloc_varsize(self, obj, flags, size):
  617. flavor = flags['flavor']
  618. zero = flags.get('zero', False)
  619. track_allocation = flags.get('track_allocation', True)
  620. assert flavor in ('gc', 'raw')
  621. try:
  622. ptr = self.heap.malloc(obj, size, zero=zero, flavor=flavor,
  623. track_allocation=track_allocation)
  624. return ptr
  625. except MemoryError:
  626. self.make_llexception()
  627. def op_malloc_nonmovable(self, TYPE, flags):
  628. flavor = flags['flavor']
  629. assert flavor == 'gc'
  630. zero = flags.get('zero', False)
  631. return self.heap.malloc_nonmovable(TYPE, zero=zero)
  632. def op_malloc_nonmovable_varsize(self, TYPE, flags, size):
  633. flavor = flags['flavor']
  634. assert flavor == 'gc'
  635. zero = flags.get('zero', False)
  636. return self.heap.malloc_nonmovable(TYPE, size, zero=zero)
  637. def op_free(self, obj, flags):
  638. assert flags['flavor'] == 'raw'
  639. track_allocation = flags.get('track_allocation', True)
  640. self.heap.free(obj, flavor='raw', track_allocation=track_allocation)
  641. def op_gc_add_memory_pressure(self, size):
  642. self.heap.add_memory_pressure(size)
  643. def op_shrink_array(self, obj, smallersize):
  644. return self.heap.shrink_array(obj, smallersize)
  645. def op_zero_gc_pointers_inside(self, obj):
  646. raise NotImplementedError("zero_gc_pointers_inside")
  647. def op_gc_writebarrier_before_copy(self, source, dest,
  648. source_start, dest_start, length):
  649. if hasattr(self.heap, 'writebarrier_before_copy'):
  650. return self.heap.writebarrier_before_copy(source, dest,
  651. source_start, dest_start,
  652. length)
  653. else:
  654. return True
  655. def op_getfield(self, obj, field):
  656. checkptr(obj)
  657. # check the difference between op_getfield and op_getsubstruct:
  658. assert not isinstance(getattr(lltype.typeOf(obj).TO, field),
  659. lltype.ContainerType)
  660. return getattr(obj, field)
  661. def op_force_cast(self, RESTYPE, obj):
  662. from rpython.rtyper.lltypesystem import ll2ctypes
  663. return ll2ctypes.force_cast(RESTYPE, obj)
  664. op_force_cast.need_result_type = True
  665. def op_cast_int_to_ptr(self, RESTYPE, int1):
  666. return lltype.cast_int_to_ptr(RESTYPE, int1)
  667. op_cast_int_to_ptr.need_result_type = True
  668. def op_cast_ptr_to_int(self, ptr1):
  669. checkptr(ptr1)
  670. return lltype.cast_ptr_to_int(ptr1)
  671. def op_cast_opaque_ptr(self, RESTYPE, obj):
  672. checkptr(obj)
  673. return lltype.cast_opaque_ptr(RESTYPE, obj)
  674. op_cast_opaque_ptr.need_result_type = True
  675. def op_cast_ptr_to_adr(self, ptr):
  676. checkptr(ptr)
  677. return llmemory.cast_ptr_to_adr(ptr)
  678. def op_cast_adr_to_int(self, adr, mode):
  679. checkadr(adr)
  680. return llmemory.cast_adr_to_int(adr, mode)
  681. def op_convert_float_bytes_to_longlong(self, f):
  682. from rpython.rlib import longlong2float
  683. return longlong2float.float2longlong(f)
  684. def op_weakref_create(self, v_obj):
  685. def objgetter(): # special support for gcwrapper.py
  686. return self.getval(v_obj)
  687. return self.heap.weakref_create_getlazy(objgetter)
  688. op_weakref_create.specialform = True
  689. def op_weakref_deref(self, PTRTYPE, obj):
  690. return self.heap.weakref_deref(PTRTYPE, obj)
  691. op_weakref_deref.need_result_type = True
  692. def op_cast_ptr_to_weakrefptr(self, obj):
  693. return llmemory.cast_ptr_to_weakrefptr(obj)
  694. def op_cast_weakrefptr_to_ptr(self, PTRTYPE, obj):
  695. return llmemory.cast_weakrefptr_to_ptr(PTRTYPE, obj)
  696. op_cast_weakrefptr_to_ptr.need_result_type = True
  697. def op_gc__collect(self, *gen):
  698. self.heap.collect(*gen)
  699. def op_gc_heap_stats(self):
  700. raise NotImplementedError
  701. def op_gc_obtain_free_space(self, size):
  702. raise NotImplementedError
  703. def op_gc_can_move(self, ptr):
  704. addr = llmemory.cast_ptr_to_adr(ptr)
  705. return self.heap.can_move(addr)
  706. def op_gc_thread_prepare(self):
  707. self.heap.thread_prepare()
  708. def op_gc_thread_run(self):
  709. self.heap.thread_run()
  710. def op_gc_thread_start(self):
  711. self.heap.thread_start()
  712. def op_gc_thread_die(self):
  713. self.heap.thread_die()
  714. def op_gc_thread_before_fork(self):
  715. raise NotImplementedError
  716. def op_gc_thread_after_fork(self):
  717. raise NotImplementedError
  718. def op_gc_free(self, addr):
  719. # what can you do?
  720. pass
  721. #raise NotImplementedError("gc_free")
  722. def op_gc_fetch_exception(self):
  723. raise NotImplementedError("gc_fetch_exception")
  724. def op_gc_restore_exception(self, exc):
  725. raise NotImplementedError("gc_restore_exception")
  726. def op_gc_adr_of_nursery_top(self):
  727. raise NotImplementedError
  728. def op_gc_adr_of_nursery_free(self):
  729. raise NotImplementedError
  730. def op_gc_adr_of_root_stack_base(self):
  731. raise NotImplementedError
  732. def op_gc_adr_of_root_stack_top(self):
  733. raise NotImplementedError
  734. def op_gc_call_rtti_destructor(self, rtti, addr):
  735. if hasattr(rtti._obj, 'destructor_funcptr'):
  736. d = rtti._obj.destructor_funcptr
  737. obptr = addr.ref()
  738. return self.op_direct_call(d, obptr)
  739. def op_gc_deallocate(self, TYPE, addr):
  740. raise NotImplementedError("gc_deallocate")
  741. def op_gc_reload_possibly_moved(self, v_newaddr, v_ptr):
  742. assert v_newaddr.concretetype is llmemory.Address
  743. assert isinstance(v_ptr.concretetype, lltype.Ptr)
  744. assert v_ptr.concretetype.TO._gckind == 'gc'
  745. newaddr = self.getval(v_newaddr)
  746. p = llmemory.cast_adr_to_ptr(newaddr, v_ptr.concretetype)
  747. if isinstance(v_ptr, Constant):
  748. assert v_ptr.value == p
  749. else:
  750. self.setvar(v_ptr, p)
  751. op_gc_reload_possibly_moved.specialform = True
  752. def op_gc_identityhash(self, obj):
  753. return lltype.identityhash(obj)
  754. def op_gc_id(self, ptr):
  755. PTR = lltype.typeOf(ptr)
  756. if isinstance(PTR, lltype.Ptr):
  757. return self.heap.gc_id(ptr)
  758. elif isinstance(PTR, ootype.OOType):
  759. return ootype.identityhash(ptr) # XXX imprecise
  760. raise NotImplementedError("gc_id on %r" % (PTR,))
  761. def op_gc_set_max_heap_size(self, maxsize):
  762. raise NotImplementedError("gc_set_max_heap_size")
  763. def op_gc_asmgcroot_static(self, index):
  764. raise NotImplementedError("gc_asmgcroot_static")
  765. def op_gc_stack_bottom(self):
  766. pass # marker for trackgcroot.py
  767. def op_gc_shadowstackref_new(self): # stacklet+shadowstack
  768. raise NotImplementedError("gc_shadowstackref_new")
  769. def op_gc_shadowstackref_context(self):
  770. raise NotImplementedError("gc_shadowstackref_context")
  771. def op_gc_save_current_state_away(self):
  772. raise NotImplementedError("gc_save_current_state_away")
  773. def op_gc_forget_current_state(self):
  774. raise NotImplementedError("gc_forget_current_state")
  775. def op_gc_restore_state_from(self):
  776. raise NotImplementedError("gc_restore_state_from")
  777. def op_gc_start_fresh_new_state(self):
  778. raise NotImplementedError("gc_start_fresh_new_state")
  779. def op_gc_get_type_info_group(self):
  780. raise NotImplementedError("gc_get_type_info_group")
  781. def op_gc_get_rpy_memory_usage(self):
  782. raise NotImplementedError("gc_get_rpy_memory_usage")
  783. def op_gc_get_rpy_roots(self):
  784. raise NotImplementedError("gc_get_rpy_roots")
  785. def op_gc_get_rpy_referents(self):
  786. raise NotImplementedError("gc_get_rpy_referents")
  787. def op_gc_is_rpy_instance(self):
  788. raise NotImplementedError("gc_is_rpy_instance")
  789. def op_gc_get_rpy_type_index(self):
  790. raise NotImplementedError("gc_get_rpy_type_index")
  791. def op_gc_dump_rpy_heap(self):
  792. raise NotImplementedError("gc_dump_rpy_heap")
  793. def op_gc_typeids_z(self):
  794. raise NotImplementedError("gc_typeids_z")
  795. def op_gc_gcflag_extra(self, subopnum, *args):
  796. return self.heap.gcflag_extra(subopnum, *args)
  797. def op_do_malloc_fixedsize_clear(self):
  798. raise NotImplementedError("do_malloc_fixedsize_clear")
  799. def op_do_malloc_varsize_clear(self):
  800. raise NotImplementedError("do_malloc_varsize_clear")
  801. def op_get_write_barrier_failing_case(self):
  802. raise NotImplementedError("get_write_barrier_failing_case")
  803. def op_get_write_barrier_from_array_failing_case(self):
  804. raise NotImplementedError("get_write_barrier_from_array_failing_case")
  805. def op_stack_current(self):
  806. return 0
  807. # __________________________________________________________
  808. # operations on addresses
  809. def op_raw_malloc(self, size):
  810. assert lltype.typeOf(size) == lltype.Signed
  811. return llmemory.raw_malloc(size)
  812. op_boehm_malloc = op_boehm_malloc_atomic = op_raw_malloc
  813. def op_boehm_register_finalizer(self, p, finalizer):
  814. pass
  815. def op_boehm_disappearing_link(self, link, obj):
  816. pass
  817. def op_raw_malloc_usage(self, size):
  818. assert lltype.typeOf(size) == lltype.Signed
  819. return llmemory.raw_malloc_usage(size)
  820. def op_raw_free(self, addr):
  821. checkadr(addr)
  822. llmemory.raw_free(addr)
  823. def op_raw_memclear(self, addr, size):
  824. checkadr(addr)
  825. llmemory.raw_memclear(addr, size)
  826. def op_raw_memcopy(self, fromaddr, toaddr, size):
  827. checkadr(fromaddr)
  828. checkadr(toaddr)
  829. llmemory.raw_memcopy(fromaddr, toaddr, size)
  830. op_raw_memmove = op_raw_memcopy # this is essentially the same here
  831. def op_raw_load(self, RESTYPE, addr, offset):
  832. checkadr(addr)
  833. if isinstance(offset, int):
  834. from rpython.rtyper.lltypesystem import rffi
  835. ll_p = rffi.cast(rffi.CCHARP, addr)
  836. ll_p = rffi.cast(rffi.CArrayPtr(RESTYPE),
  837. rffi.ptradd(ll_p, offset))
  838. value = ll_p[0]
  839. else:
  840. assert offset.TYPE == RESTYPE
  841. value = getattr(addr, str(RESTYPE).lower())[offset.repeat]
  842. assert lltype.typeOf(value) == RESTYPE
  843. return value
  844. op_raw_load.need_result_type = True
  845. def op_raw_store(self, addr, offset, value):
  846. checkadr(addr)
  847. ARGTYPE = lltype.typeOf(value)
  848. if isinstance(offset, int):
  849. from rpython.rtyper.lltypesystem import rffi
  850. ll_p = rffi.cast(rffi.CCHARP, addr)
  851. ll_p = rffi.cast(rffi.CArrayPtr(ARGTYPE),
  852. rffi.ptradd(ll_p, offset))
  853. ll_p[0] = value
  854. else:
  855. assert offset.TYPE == ARGTYPE
  856. getattr(addr, str(ARGTYPE).lower())[offset.repeat] = value
  857. def op_stack_malloc(self, size): # mmh
  858. raise NotImplementedError("backend only")
  859. def op_track_alloc_start(self, addr):
  860. # we don't do tracking at this level
  861. checkadr(addr)
  862. def op_track_alloc_stop(self, addr):
  863. checkadr(addr)
  864. # ____________________________________________________________
  865. # Overflow-detecting variants
  866. def op_int_neg_ovf(self, x):
  867. assert is_valid_int(x)
  868. try:
  869. return ovfcheck(-x)
  870. except OverflowError:
  871. self.make_llexception()
  872. def op_int_abs_ovf(self, x):
  873. assert is_valid_int(x)
  874. try:
  875. return ovfcheck(abs(x))
  876. except OverflowError:
  877. self.make_llexception()
  878. def op_int_lshift_ovf(self, x, y):
  879. assert is_valid_int(x)
  880. assert is_valid_int(y)
  881. try:
  882. return ovfcheck(x << y)
  883. except OverflowError:
  884. self.make_llexception()
  885. def _makefunc2(fn, operator, xtype, ytype=None):
  886. import sys
  887. d = sys._getframe(1).f_locals
  888. if ytype is None:
  889. ytype = xtype
  890. if '_ovf' in fn:
  891. checkfn = 'ovfcheck'
  892. elif fn.startswith('op_int_'):
  893. checkfn = 'intmask'
  894. else:
  895. checkfn = ''
  896. if operator == '//':
  897. code = '''r = %(checkfn)s(x // y)
  898. if x^y < 0 and x%%y != 0:
  899. r += 1
  900. return r
  901. ''' % locals()
  902. elif operator == '%':
  903. ## overflow check on % does not work with emulated int
  904. code = '''%(checkfn)s(x // y)
  905. r = x %% y
  906. if x^y < 0 and x%%y != 0:
  907. r -= y
  908. return r
  909. ''' % locals()
  910. else:
  911. code = 'return %(checkfn)s(x %(operator)s y)' % locals()
  912. exec py.code.Source("""
  913. def %(fn)s(self, x, y):
  914. assert isinstance(x, %(xtype)s)
  915. assert isinstance(y, %(ytype)s)
  916. try:
  917. %(code)s
  918. except (OverflowError, ValueError, ZeroDivisionError):
  919. self.make_llexception()
  920. """ % locals()).compile() in globals(), d
  921. _makefunc2('op_int_add_ovf', '+', '(int, long, llmemory.AddressOffset)')
  922. _makefunc2('op_int_mul_ovf', '*', '(int, long, llmemory.AddressOffset)', '(int, long)')
  923. _makefunc2('op_int_sub_ovf', '-', '(int, long)')
  924. _makefunc2('op_int_floordiv_ovf', '//', '(int, long)') # XXX negative args
  925. _makefunc2('op_int_floordiv_zer', '//', '(int, long)') # can get off-by-one
  926. _makefunc2('op_int_floordiv_ovf_zer', '//', '(int, long)') # (see op_int_floordiv)
  927. _makefunc2('op_int_mod_ovf', '%', '(int, long)')
  928. _makefunc2('op_int_mod_zer', '%', '(int, long)')
  929. _makefunc2('op_int_mod_ovf_zer', '%', '(int, long)')
  930. _makefunc2('op_uint_floordiv_zer', '//', 'r_uint')
  931. _makefunc2('op_uint_mod_zer', '%', 'r_uint')
  932. _makefunc2('op_llong_floordiv_zer', '//', 'r_longlong')
  933. _makefunc2('op_llong_mod_zer', '%', 'r_longlong')
  934. _makefunc2('op_ullong_floordiv_zer', '//', 'r_ulonglong')
  935. _makefunc2('op_ullong_mod_zer', '%', 'r_ulonglong')
  936. _makefunc2('op_lllong_floordiv_zer', '//', 'r_longlonglong')
  937. _makefunc2('op_lllong_mod_zer', '%', 'r_longlonglong')
  938. def op_int_add_nonneg_ovf(self, x, y):
  939. if isinstance(y, int):
  940. assert y >= 0
  941. return self.op_int_add_ovf(x, y)
  942. def op_int_is_true(self, x):
  943. # special case
  944. if type(x) is CDefinedIntSymbolic:
  945. x = x.default
  946. # if type(x) is a subclass of Symbolic, bool(x) will usually raise
  947. # a TypeError -- unless __nonzero__ has been explicitly overridden.
  948. assert is_valid_int(x) or isinstance(x, Symbolic)
  949. return bool(x)
  950. # hack for jit.codegen.llgraph
  951. def op_check_and_clear_exc(self):
  952. exc_data = self.llinterpreter.get_transformed_exc_data(self.graph)
  953. assert exc_data
  954. etype = exc_data.exc_type
  955. evalue = exc_data.exc_value
  956. exc_data.exc_type = lltype.typeOf(etype)._defl()
  957. exc_data.exc_value = lltype.typeOf(evalue)._defl()
  958. return bool(etype)
  959. #Operation of ootype
  960. def op_new(self, INST):
  961. assert isinstance(INST, (ootype.Instance, ootype.BuiltinType))
  962. return ootype.new(INST)
  963. def op_oonewarray(self, ARRAY, length):
  964. assert isinstance(ARRAY, ootype.Array)
  965. assert is_valid_int(length)
  966. return ootype.oonewarray(ARRAY, length)
  967. def op_runtimenew(self, class_):
  968. return ootype.runtimenew(class_)
  969. def op_oonewcustomdict(self, DICT, eq_func, eq_obj, eq_method_name,
  970. hash_func, hash_obj, hash_method_name):
  971. eq_name, interp_eq = \
  972. wrap_callable(self.llinterpreter, eq_func, eq_obj, eq_method_name)
  973. EQ_FUNC = ootype.StaticMethod([DICT._KEYTYPE, DICT._KEYTYPE], ootype.Bool)
  974. sm_eq = ootype.static_meth(EQ_FUNC, eq_name, _callable=interp_eq)
  975. hash_name, interp_hash = \
  976. wrap_callable(self.llinterpreter, hash_func, hash_obj, hash_method_name)
  977. HASH_FUNC = ootype.StaticMethod([DICT._KEYTYPE], ootype.Signed)
  978. sm_hash = ootype.static_meth(HASH_FUNC, hash_name, _callable=interp_hash)
  979. # XXX: is it fine to have StaticMethod type for bound methods, too?
  980. return ootype.oonewcustomdict(DICT, sm_eq, sm_hash)
  981. def op_oosetfield(self, inst, name, value):
  982. checkinst(inst)
  983. assert isinstance(name, str)
  984. FIELDTYPE = lltype.typeOf(inst)._field_type(name)
  985. if FIELDTYPE is not lltype.Void:
  986. setattr(inst, name, value)
  987. def op_oogetfield(self, inst, name):
  988. checkinst(inst)
  989. assert isinstance(name, str)
  990. return getattr(inst, name)
  991. def op_oosend(self, message, inst, *args):
  992. checkinst(inst)
  993. assert isinstance(message, str)
  994. bm = getattr(inst, message)
  995. inst = bm.inst
  996. m = bm.meth
  997. args = m._checkargs(args, check_callable=False)
  998. if getattr(m, 'abstract', False):
  999. raise RuntimeError("calling abstract method %r" % (m,))
  1000. return self.perform_call(m, (lltype.typeOf(inst),)+lltype.typeOf(m).ARGS, [inst]+args)
  1001. def op_oostring(self, obj, base):
  1002. return ootype.oostring(obj, base)
  1003. def op_oounicode(self, obj, base):
  1004. try:
  1005. return ootype.oounicode(obj, base)
  1006. except UnicodeDecodeError:
  1007. self.make_llexception()
  1008. def op_ooparse_int(self, s, base):
  1009. try:
  1010. return ootype.ooparse_int(s, base)
  1011. except ValueError:
  1012. self.make_llexception()
  1013. def op_ooparse_float(self, s):
  1014. try:
  1015. return ootype.ooparse_float(s)
  1016. except ValueError:
  1017. self.make_llexception()
  1018. def op_oobox_int(self, i):
  1019. return ootype.oobox_int(i)
  1020. def op_oounbox_int(self, x):
  1021. return ootype.oounbox_int(x)
  1022. class Tracer(object):
  1023. Counter = 0
  1024. file = None
  1025. TRACE = int(os.getenv('PYPY_TRACE') or '0')
  1026. HEADER = """<html><head>
  1027. <script language=javascript type='text/javascript'>
  1028. function togglestate(n) {
  1029. var item = document.getElementById('div'+n)
  1030. if (item.style.display == 'none')
  1031. item.style.display = 'block';
  1032. else
  1033. item.style.display = 'none';
  1034. }
  1035. function toggleall(lst) {
  1036. for (var i = 0; i<lst.length; i++) {
  1037. togglestate(lst[i]);
  1038. }
  1039. }
  1040. </script>
  1041. </head>
  1042. <body><pre>
  1043. """
  1044. FOOTER = """</pre>
  1045. <script language=javascript type='text/javascript'>
  1046. toggleall(%r);
  1047. </script>
  1048. </body></html>"""
  1049. ENTER = ('''\n\t<a href="javascript:togglestate(%d)">%s</a>'''
  1050. '''\n<div id="div%d" style="display: %s">\t''')
  1051. LEAVE = '''\n</div>\t'''
  1052. def htmlquote(self, s, text_to_html={}):
  1053. # HTML quoting, lazily initialized
  1054. if not text_to_html:
  1055. import htmlentitydefs
  1056. for key, value in htmlentitydefs.entitydefs.items():
  1057. text_to_html[value] = '&' + key + ';'
  1058. return ''.join([text_to_html.get(c, c) for c in s])
  1059. def start(self):
  1060. # start of a dump file
  1061. if not self.TRACE:
  1062. return
  1063. from rpython.tool.udir import udir
  1064. n = Tracer.Counter
  1065. Tracer.Counter += 1
  1066. filename = 'llinterp_trace_%d.html' % n
  1067. self.file = udir.join(filename).open('w')
  1068. print >> self.file, self.HEADER
  1069. linkname = str(udir.join('llinterp_trace.html'))
  1070. try:
  1071. os.unlink(linkname)
  1072. except OSError:
  1073. pass
  1074. try:
  1075. os.symlink(filename, linkname)
  1076. except (AttributeError, OSError):
  1077. pass
  1078. self.count = 0
  1079. self.indentation = ''
  1080. self.depth = 0
  1081. self.latest_call_chain = []
  1082. def stop(self):
  1083. # end of a dump file
  1084. if self.file:
  1085. print >> self.file, self.FOOTER % (self.latest_call_chain[1:])
  1086. self.file.close()
  1087. self.file = None
  1088. def enter(self, graph):
  1089. # enter evaluation of a graph
  1090. if self.file:
  1091. del self.latest_call_chain[self.depth:]
  1092. self.depth += 1
  1093. self.latest_call_chain.append(self.count)
  1094. s = self.htmlquote(str(graph))
  1095. i = s.rfind(')')
  1096. s = s[:i+1] + '<b>' + s[i+1:] + '</b>'
  1097. if self.count == 0:
  1098. display = 'block'
  1099. else:
  1100. display = 'none'
  1101. text = self.ENTER % (self.count, s, self.count, display)
  1102. self.indentation += ' '
  1103. self.file.write(text.replace('\t', self.indentation))
  1104. self.count += 1
  1105. def leave(self):
  1106. # leave evaluation of a graph
  1107. if self.file:
  1108. self.indentation = self.indentation[:-4]
  1109. self.file.write(self.LEAVE.replace('\t', self.indentation))
  1110. self.depth -= 1
  1111. def dump(self, text, bold=False):
  1112. if self.file:
  1113. text = self.htmlquote(text)
  1114. if bold:
  1115. text = '<b>%s</b>' % (text,)
  1116. self.file.write(text.replace('\n', '\n'+self.indentation))
  1117. def flush(self):
  1118. if self.file:
  1119. self.file.flush()
  1120. def wrap_callable(llinterpreter, fn, obj, method_name):
  1121. if method_name is None:
  1122. # fn is a StaticMethod
  1123. if obj is not None:
  1124. self_arg = [obj]
  1125. else:
  1126. self_arg = []
  1127. func_graph = fn.graph
  1128. else:
  1129. # obj is an instance, we want to call 'method_name' on it
  1130. assert fn is None
  1131. self_arg = [obj]
  1132. func_graph = obj._TYPE._methods[method_name._str].graph
  1133. return wrap_graph(llinterpreter, func_graph, self_arg)
  1134. def wrap_graph(llinterpreter, graph, self_arg):
  1135. """
  1136. Returns a callable that inteprets the given func or method_name when called.
  1137. """
  1138. def interp_func(*args):
  1139. graph_args = self_arg + list(args)
  1140. return llinterpreter.eval_graph(graph, args=graph_args)
  1141. interp_func.graph = graph
  1142. interp_func.self_arg = self_arg
  1143. return graph.name, interp_func
  1144. def enumerate_exceptions_top_down():
  1145. import exceptions
  1146. result = []
  1147. seen = {}
  1148. def addcls(cls):
  1149. if (type(cls) is type(Exception) and
  1150. issubclass(cls, py.builtin.BaseException)):
  1151. if cls in seen:
  1152. return
  1153. for base in cls.__bases__: # bases first
  1154. addcls(base)
  1155. result.append(cls)
  1156. seen[cls] = True
  1157. for cls in exceptions.__dict__.values():
  1158. addcls(cls)
  1159. return result
  1160. class _address_of_local_var(object):
  1161. _TYPE = llmemory.Address
  1162. def __init__(self, frame, v):
  1163. self._frame = frame
  1164. self._v = v
  1165. def _getaddress(self):
  1166. return _address_of_local_var_accessor(self._frame, self._v)
  1167. address = property(_getaddress)
  1168. class _address_of_local_var_accessor(object):
  1169. def __init__(self, frame, v):
  1170. self.frame = frame
  1171. self.v = v
  1172. def __getitem__(self, index):
  1173. if index != 0:
  1174. raise IndexError("address of local vars only support [0] indexing")
  1175. p = self.frame.getval(self.v)
  1176. result = llmemory.cast_ptr_to_adr(p)
  1177. # the GC should never see instances of _gctransformed_wref
  1178. result = self.unwrap_possible_weakref(result)
  1179. return result
  1180. def __setitem__(self, index, newvalue):
  1181. if index != 0:
  1182. raise IndexError("address of local vars only support [0] indexing")
  1183. if self.v.concretetype == llmemory.WeakRefPtr:
  1184. # fish some more
  1185. assert isinstance(newvalue, llmemory.fakeaddress)
  1186. p = llmemory.cast_ptr_to_weakrefptr(newvalue.ptr)
  1187. else:
  1188. p = llmemory.cast_adr_to_ptr(newvalue, self.v.concretetype)
  1189. self.frame.setvar(self.v, p)
  1190. def unwrap_possible_weakref(self, addr):
  1191. # fish fish fish
  1192. if addr and isinstance(addr.ptr._obj, llmemory._gctransformed_wref):
  1193. return llmemory.fakeaddress(addr.ptr._obj._ptr)
  1194. return addr
  1195. # by default we route all logging messages to nothingness
  1196. # e.g. tests can then switch on logging to get more help
  1197. # for failing tests
  1198. from rpython.tool.ansi_print import ansi_log
  1199. py.log.setconsumer('llinterp', ansi_log)