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

/rpython/rtyper/llinterp.py

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