PageRenderTime 68ms CodeModel.GetById 23ms RepoModel.GetById 0ms app.codeStats 1ms

/pypy/rpython/lltypesystem/llmemory.py

http://github.com/pypy/pypy
Python | 889 lines | 674 code | 142 blank | 73 comment | 146 complexity | 471e0a59f05bc824acd32cfe0bd1306f MD5 | raw file
  1. # this file contains the definitions and most extremely faked
  2. # implementations of things relating to the description of the layout
  3. # of objects in memeory.
  4. # sizeof, offsetof
  5. import weakref
  6. from pypy.rlib.objectmodel import Symbolic
  7. from pypy.rpython.lltypesystem import lltype
  8. from pypy.tool.uid import uid
  9. from pypy.rlib.rarithmetic import is_valid_int
  10. class AddressOffset(Symbolic):
  11. def annotation(self):
  12. from pypy.annotation import model
  13. return model.SomeInteger()
  14. def lltype(self):
  15. return lltype.Signed
  16. def __add__(self, other):
  17. if not isinstance(other, AddressOffset):
  18. return NotImplemented
  19. return CompositeOffset(self, other)
  20. # special-casing: only for '>= 0' and '< 0' and only when the
  21. # symbolic offset is known to be non-negative
  22. def __ge__(self, other):
  23. if self is other:
  24. return True
  25. elif (is_valid_int(other) and other == 0 and
  26. self.known_nonneg()):
  27. return True
  28. else:
  29. raise TypeError("Symbolics cannot be compared! (%r, %r)"
  30. % (self, other))
  31. def __lt__(self, other):
  32. return not self.__ge__(other)
  33. def known_nonneg(self):
  34. return False
  35. def _raw_malloc(self, rest, zero):
  36. raise NotImplementedError("_raw_malloc(%r, %r)" % (self, rest))
  37. def raw_memcopy(self, srcadr, dstadr):
  38. raise NotImplementedError("raw_memcopy(%r)" % (self,))
  39. class ItemOffset(AddressOffset):
  40. def __init__(self, TYPE, repeat=1):
  41. self.TYPE = TYPE
  42. self.repeat = repeat
  43. def __repr__(self):
  44. return "<ItemOffset %r %r>" % (self.TYPE, self.repeat)
  45. def __mul__(self, other):
  46. if not is_valid_int(other):
  47. return NotImplemented
  48. return ItemOffset(self.TYPE, self.repeat * other)
  49. __rmul__ = __mul__
  50. def __neg__(self):
  51. return ItemOffset(self.TYPE, -self.repeat)
  52. def known_nonneg(self):
  53. return self.repeat >= 0
  54. def ref(self, firstitemptr):
  55. A = lltype.typeOf(firstitemptr).TO
  56. if A == self.TYPE:
  57. # for array of containers
  58. parent, index = lltype.parentlink(firstitemptr._obj)
  59. assert parent, "%r is not within a container" % (firstitemptr,)
  60. assert isinstance(lltype.typeOf(parent),
  61. (lltype.Array, lltype.FixedSizeArray)), (
  62. "%r is not within an array" % (firstitemptr,))
  63. if isinstance(index, str):
  64. assert index.startswith('item') # itemN => N
  65. index = int(index[4:])
  66. index += self.repeat
  67. if index == parent.getlength():
  68. # for references exactly to the end of the array
  69. try:
  70. endmarker = _end_markers[parent]
  71. except KeyError:
  72. endmarker = _endmarker_struct(A, parent=parent,
  73. parentindex=index)
  74. _end_markers[parent] = endmarker
  75. return endmarker._as_ptr()
  76. else:
  77. return parent.getitem(index)._as_ptr()
  78. elif ((isinstance(A, lltype.FixedSizeArray)
  79. or (isinstance(A, lltype.Array) and A._hints.get('nolength',
  80. False)))
  81. and array_item_type_match(A.OF, self.TYPE)):
  82. # for array of primitives or pointers
  83. return lltype.direct_ptradd(firstitemptr, self.repeat)
  84. else:
  85. raise TypeError('got %r, expected %r' % (A, self.TYPE))
  86. def _raw_malloc(self, rest, zero):
  87. assert not rest
  88. if (isinstance(self.TYPE, lltype.ContainerType)
  89. and self.TYPE._gckind == 'gc'):
  90. assert self.repeat == 1
  91. p = lltype.malloc(self.TYPE, flavor='raw', zero=zero,
  92. track_allocation=False)
  93. return cast_ptr_to_adr(p)
  94. else:
  95. T = lltype.FixedSizeArray(self.TYPE, self.repeat)
  96. p = lltype.malloc(T, flavor='raw', zero=zero,
  97. track_allocation=False)
  98. array_adr = cast_ptr_to_adr(p)
  99. return array_adr + ArrayItemsOffset(T)
  100. def raw_memcopy(self, srcadr, dstadr):
  101. repeat = self.repeat
  102. if repeat == 0:
  103. return
  104. if isinstance(self.TYPE, lltype.ContainerType):
  105. PTR = lltype.Ptr(self.TYPE)
  106. elif self.TYPE == GCREF:
  107. self._raw_memcopy_gcrefs(srcadr, dstadr)
  108. return
  109. else:
  110. PTR = lltype.Ptr(lltype.FixedSizeArray(self.TYPE, 1))
  111. while True:
  112. src = cast_adr_to_ptr(srcadr, PTR)
  113. dst = cast_adr_to_ptr(dstadr, PTR)
  114. _reccopy(src, dst)
  115. repeat -= 1
  116. if repeat <= 0:
  117. break
  118. srcadr += ItemOffset(self.TYPE)
  119. dstadr += ItemOffset(self.TYPE)
  120. def _raw_memcopy_gcrefs(self, srcadr, dstadr):
  121. # special case to handle arrays of any GC pointers
  122. repeat = self.repeat
  123. while True:
  124. data = srcadr.address[0]
  125. dstadr.address[0] = data
  126. repeat -= 1
  127. if repeat <= 0:
  128. break
  129. srcadr += ItemOffset(self.TYPE)
  130. dstadr += ItemOffset(self.TYPE)
  131. _end_markers = weakref.WeakKeyDictionary() # <array of STRUCT> -> _endmarker
  132. class _endmarker_struct(lltype._struct):
  133. __slots__ = ()
  134. def __new__(self, *args, **kwds):
  135. return object.__new__(self)
  136. def __init__(self, *args, **kwds):
  137. lltype._struct.__init__(self, *args, **kwds)
  138. self._storage = False
  139. def __getattr__(self, name):
  140. raise AttributeError("cannot access fields in the endmarker "
  141. "structure at the end of the array")
  142. def __setattr__(self, name, value):
  143. if name.startswith('_'):
  144. object.__setattr__(self, name, value) # '_xxx' attributes
  145. elif self._storage is False:
  146. raise AttributeError("cannot access fields in the endmarker "
  147. "structure at the end of the array")
  148. class FieldOffset(AddressOffset):
  149. def __init__(self, TYPE, fldname):
  150. self.TYPE = TYPE
  151. self.fldname = fldname
  152. def __repr__(self):
  153. return "<FieldOffset %r %r>" % (self.TYPE, self.fldname)
  154. def known_nonneg(self):
  155. return True
  156. def ref(self, struct):
  157. if lltype.typeOf(struct).TO != self.TYPE:
  158. struct = lltype.cast_pointer(lltype.Ptr(self.TYPE), struct)
  159. FIELD = getattr(self.TYPE, self.fldname)
  160. if isinstance(FIELD, lltype.ContainerType):
  161. substruct = struct._obj._getattr(self.fldname)
  162. return substruct._as_ptr()
  163. else:
  164. return lltype.direct_fieldptr(struct, self.fldname)
  165. def _raw_malloc(self, rest, parenttype=None, zero=False):
  166. if self.fldname != self.TYPE._arrayfld:
  167. # for the error msg
  168. return AddressOffset._raw_malloc(self, rest, zero=zero)
  169. assert rest
  170. return rest[0]._raw_malloc(rest[1:], parenttype=parenttype or self.TYPE,
  171. zero=zero)
  172. def raw_memcopy(self, srcadr, dstadr):
  173. if self.fldname != self.TYPE._arrayfld:
  174. return AddressOffset.raw_memcopy(srcadr, dstadr) #for the error msg
  175. PTR = lltype.Ptr(self.TYPE)
  176. src = cast_adr_to_ptr(srcadr, PTR)
  177. dst = cast_adr_to_ptr(dstadr, PTR)
  178. _reccopy(src, dst)
  179. class CompositeOffset(AddressOffset):
  180. def __new__(cls, *offsets):
  181. lst = []
  182. for item in offsets:
  183. if isinstance(item, CompositeOffset):
  184. lst.extend(item.offsets)
  185. else:
  186. lst.append(item)
  187. for i in range(len(lst)-2, -1, -1):
  188. if (isinstance(lst[i], ItemOffset) and
  189. isinstance(lst[i+1], ItemOffset) and
  190. lst[i].TYPE == lst[i+1].TYPE):
  191. lst[i:i+2] = [ItemOffset(lst[i].TYPE,
  192. lst[i].repeat + lst[i+1].repeat)]
  193. if len(lst) == 1:
  194. return lst[0]
  195. else:
  196. self = object.__new__(cls)
  197. self.offsets = lst
  198. return self
  199. def __repr__(self):
  200. return '< %s >' % (' + '.join([repr(item) for item in self.offsets]),)
  201. def __neg__(self):
  202. ofs = [-item for item in self.offsets]
  203. ofs.reverse()
  204. return CompositeOffset(*ofs)
  205. def known_nonneg(self):
  206. for item in self.offsets:
  207. if not item.known_nonneg():
  208. return False
  209. return True
  210. def ref(self, ptr):
  211. for item in self.offsets:
  212. ptr = item.ref(ptr)
  213. return ptr
  214. def _raw_malloc(self, rest, zero):
  215. return self.offsets[0]._raw_malloc(self.offsets[1:] + rest, zero=zero)
  216. def raw_memcopy(self, srcadr, dstadr):
  217. for o in self.offsets[:-1]:
  218. o.raw_memcopy(srcadr, dstadr)
  219. srcadr += o
  220. dstadr += o
  221. o = self.offsets[-1]
  222. o.raw_memcopy(srcadr, dstadr)
  223. class ArrayItemsOffset(AddressOffset):
  224. def __init__(self, TYPE):
  225. self.TYPE = TYPE
  226. def __repr__(self):
  227. return '< ArrayItemsOffset %r >' % (self.TYPE,)
  228. def known_nonneg(self):
  229. return True
  230. def ref(self, arrayptr):
  231. assert array_type_match(lltype.typeOf(arrayptr).TO, self.TYPE)
  232. if isinstance(self.TYPE.OF, lltype.ContainerType):
  233. # XXX this doesn't support empty arrays
  234. # XXX it's also missing 'solid' support, probably
  235. o = arrayptr._obj.getitem(0)
  236. return o._as_ptr()
  237. else:
  238. return lltype.direct_arrayitems(arrayptr)
  239. def _raw_malloc(self, rest, parenttype=None, zero=False):
  240. if rest:
  241. assert len(rest) == 1
  242. assert isinstance(rest[0], ItemOffset)
  243. assert self.TYPE.OF == rest[0].TYPE
  244. count = rest[0].repeat
  245. else:
  246. count = 0
  247. p = lltype.malloc(parenttype or self.TYPE, count,
  248. immortal = self.TYPE._gckind == 'raw',
  249. zero = zero,
  250. track_allocation = False)
  251. return cast_ptr_to_adr(p)
  252. def raw_memcopy(self, srcadr, dstadr):
  253. # should really copy the length field, but we can't
  254. pass
  255. class ArrayLengthOffset(AddressOffset):
  256. def __init__(self, TYPE):
  257. self.TYPE = TYPE
  258. def __repr__(self):
  259. return '< ArrayLengthOffset %r >' % (self.TYPE,)
  260. def known_nonneg(self):
  261. return True
  262. def ref(self, arrayptr):
  263. assert array_type_match(lltype.typeOf(arrayptr).TO, self.TYPE)
  264. return lltype._arraylenref._makeptr(arrayptr._obj, arrayptr._solid)
  265. class GCHeaderOffset(AddressOffset):
  266. def __init__(self, gcheaderbuilder):
  267. self.gcheaderbuilder = gcheaderbuilder
  268. def __repr__(self):
  269. return '< GCHeaderOffset >'
  270. def __neg__(self):
  271. return GCHeaderAntiOffset(self.gcheaderbuilder)
  272. def known_nonneg(self):
  273. return True
  274. def ref(self, headerptr):
  275. gcptr = self.gcheaderbuilder.object_from_header(headerptr)
  276. return gcptr
  277. def _raw_malloc(self, rest, zero):
  278. assert rest
  279. if isinstance(rest[0], GCHeaderAntiOffset):
  280. return rest[1]._raw_malloc(rest[2:], zero=zero) # just for fun
  281. gcobjadr = rest[0]._raw_malloc(rest[1:], zero=zero)
  282. headerptr = self.gcheaderbuilder.new_header(gcobjadr.ptr)
  283. return cast_ptr_to_adr(headerptr)
  284. def raw_memcopy(self, srcadr, dstadr):
  285. _reccopy(srcadr.ptr, dstadr.ptr)
  286. class GCHeaderAntiOffset(AddressOffset):
  287. def __init__(self, gcheaderbuilder):
  288. self.gcheaderbuilder = gcheaderbuilder
  289. def __repr__(self):
  290. return '< GCHeaderAntiOffset >'
  291. def __neg__(self):
  292. return GCHeaderOffset(self.gcheaderbuilder)
  293. def ref(self, gcptr):
  294. headerptr = self.gcheaderbuilder.header_of_object(gcptr)
  295. return headerptr
  296. def _raw_malloc(self, rest, zero):
  297. assert len(rest) >= 2
  298. assert isinstance(rest[0], GCHeaderOffset)
  299. return rest[1]._raw_malloc(rest[2:], zero=zero)
  300. # ____________________________________________________________
  301. def _sizeof_none(TYPE):
  302. assert not TYPE._is_varsize()
  303. return ItemOffset(TYPE)
  304. _sizeof_none._annspecialcase_ = 'specialize:memo'
  305. def _sizeof_int(TYPE, n):
  306. "NOT_RPYTHON"
  307. if isinstance(TYPE, lltype.Struct):
  308. return FieldOffset(TYPE, TYPE._arrayfld) + \
  309. itemoffsetof(TYPE._flds[TYPE._arrayfld], n)
  310. else:
  311. raise Exception("don't know how to take the size of a %r"%TYPE)
  312. def sizeof(TYPE, n=None):
  313. if n is None:
  314. return _sizeof_none(TYPE)
  315. elif isinstance(TYPE, lltype.Array):
  316. return itemoffsetof(TYPE) + _sizeof_none(TYPE.OF) * n
  317. else:
  318. return _sizeof_int(TYPE, n)
  319. sizeof._annspecialcase_ = 'specialize:arg(0)'
  320. def offsetof(TYPE, fldname):
  321. assert fldname in TYPE._flds
  322. return FieldOffset(TYPE, fldname)
  323. offsetof._annspecialcase_ = 'specialize:memo'
  324. def itemoffsetof(TYPE, n=0):
  325. result = ArrayItemsOffset(TYPE)
  326. if n != 0:
  327. result += ItemOffset(TYPE.OF) * n
  328. return result
  329. itemoffsetof._annspecialcase_ = 'specialize:memo'
  330. # -------------------------------------------------------------
  331. class fakeaddress(object):
  332. __slots__ = ['ptr']
  333. # NOTE: the 'ptr' in the addresses must be normalized.
  334. # Use cast_ptr_to_adr() instead of directly fakeaddress() if unsure.
  335. def __init__(self, ptr):
  336. if ptr is not None and ptr._obj0 is None:
  337. ptr = None # null ptr => None
  338. self.ptr = ptr
  339. def __repr__(self):
  340. if self.ptr is None:
  341. s = 'NULL'
  342. else:
  343. #try:
  344. # s = hex(self.ptr._cast_to_int())
  345. #except:
  346. s = str(self.ptr)
  347. return '<fakeaddr %s>' % (s,)
  348. def __add__(self, other):
  349. if isinstance(other, AddressOffset):
  350. if self.ptr is None:
  351. raise NullAddressError("offset from NULL address")
  352. return fakeaddress(other.ref(self.ptr))
  353. if other == 0:
  354. return self
  355. return NotImplemented
  356. def __sub__(self, other):
  357. if isinstance(other, AddressOffset):
  358. return self + (-other)
  359. if isinstance(other, fakeaddress):
  360. if self == other:
  361. return 0
  362. else:
  363. raise TypeError("cannot subtract fakeaddresses in general")
  364. if other == 0:
  365. return self
  366. return NotImplemented
  367. def __nonzero__(self):
  368. return self.ptr is not None
  369. #def __hash__(self):
  370. # raise TypeError("don't put addresses in a prebuilt dictionary")
  371. def __eq__(self, other):
  372. if isinstance(other, fakeaddress):
  373. try:
  374. obj1 = self._fixup().ptr
  375. obj2 = other._fixup().ptr
  376. if obj1 is not None: obj1 = obj1._obj
  377. if obj2 is not None: obj2 = obj2._obj
  378. return obj1 == obj2
  379. except lltype.DelayedPointer:
  380. return self.ptr is other.ptr
  381. else:
  382. return NotImplemented
  383. def __ne__(self, other):
  384. if isinstance(other, fakeaddress):
  385. return not (self == other)
  386. else:
  387. return NotImplemented
  388. def __lt__(self, other):
  389. # for the convenience of debugging the GCs, NULL compares as the
  390. # smallest address even when compared with a non-fakearenaaddress
  391. if not isinstance(other, fakeaddress):
  392. raise TypeError("cannot compare fakeaddress and %r" % (
  393. other.__class__.__name__,))
  394. if not other:
  395. return False # self < NULL => False
  396. if not self:
  397. return True # NULL < non-null-other => True
  398. raise TypeError("cannot compare non-NULL fakeaddresses with '<'")
  399. def __le__(self, other):
  400. return self == other or self < other
  401. def __gt__(self, other):
  402. return not (self == other or self < other)
  403. def __ge__(self, other):
  404. return not (self < other)
  405. def ref(self):
  406. if not self:
  407. raise NullAddressError
  408. return self.ptr
  409. def _cast_to_ptr(self, EXPECTED_TYPE):
  410. addr = self._fixup()
  411. if addr:
  412. return cast_any_ptr(EXPECTED_TYPE, addr.ptr)
  413. else:
  414. return lltype.nullptr(EXPECTED_TYPE.TO)
  415. def _cast_to_int(self, symbolic=False):
  416. if self:
  417. if isinstance(self.ptr._obj0, int): # tagged integer
  418. return self.ptr._obj0
  419. if symbolic:
  420. return AddressAsInt(self)
  421. else:
  422. # This is a bit annoying. We want this method to still work
  423. # when the pointed-to object is dead
  424. return self.ptr._cast_to_int(False)
  425. else:
  426. return 0
  427. def _fixup(self):
  428. if self.ptr is not None and self.ptr._was_freed():
  429. # hack to support llarena.test_replace_object_with_stub()
  430. from pypy.rpython.lltypesystem import llarena
  431. return llarena.getfakearenaaddress(self)
  432. else:
  433. return self
  434. # ____________________________________________________________
  435. class AddressAsInt(Symbolic):
  436. # a symbolic, rendered as an address cast to an integer.
  437. def __init__(self, adr):
  438. self.adr = adr
  439. def annotation(self):
  440. from pypy.annotation import model
  441. return model.SomeInteger()
  442. def lltype(self):
  443. return lltype.Signed
  444. def __eq__(self, other):
  445. return self.adr == cast_int_to_adr(other)
  446. def __ne__(self, other):
  447. return self.adr != cast_int_to_adr(other)
  448. def __nonzero__(self):
  449. return bool(self.adr)
  450. def __repr__(self):
  451. try:
  452. return '<AddressAsInt %s>' % (self.adr.ptr,)
  453. except AttributeError:
  454. return '<AddressAsInt at 0x%x>' % (uid(self),)
  455. # ____________________________________________________________
  456. class NullAddressError(Exception):
  457. pass
  458. class DanglingPointerError(Exception):
  459. pass
  460. NULL = fakeaddress(None)
  461. Address = lltype.Primitive("Address", NULL)
  462. # GCREF is similar to Address but it is GC-aware
  463. GCREF = lltype.Ptr(lltype.GcOpaqueType('GCREF'))
  464. # A placeholder for any type that is a GcArray of pointers.
  465. # This can be used in the symbolic offsets above to access such arrays
  466. # in a generic way.
  467. GCARRAY_OF_PTR = lltype.GcArray(GCREF, hints={'placeholder': True})
  468. gcarrayofptr_lengthoffset = ArrayLengthOffset(GCARRAY_OF_PTR)
  469. gcarrayofptr_itemsoffset = ArrayItemsOffset(GCARRAY_OF_PTR)
  470. gcarrayofptr_singleitemoffset = ItemOffset(GCARRAY_OF_PTR.OF)
  471. def array_type_match(A1, A2):
  472. return A1 == A2 or (A2 == GCARRAY_OF_PTR and
  473. isinstance(A1, lltype.GcArray) and
  474. isinstance(A1.OF, lltype.Ptr) and
  475. not A1._hints.get('nolength'))
  476. def array_item_type_match(T1, T2):
  477. return T1 == T2 or (T2 == GCREF and isinstance(T1, lltype.Ptr))
  478. class _fakeaccessor(object):
  479. def __init__(self, addr):
  480. self.addr = addr
  481. def __getitem__(self, index):
  482. ptr = self.addr.ref()
  483. if index != 0:
  484. ptr = lltype.direct_ptradd(ptr, index)
  485. return self.read_from_ptr(ptr)
  486. def __setitem__(self, index, value):
  487. assert lltype.typeOf(value) == self.TYPE
  488. ptr = self.addr.ref()
  489. if index != 0:
  490. ptr = lltype.direct_ptradd(ptr, index)
  491. self.write_into_ptr(ptr, value)
  492. def read_from_ptr(self, ptr):
  493. value = ptr[0]
  494. assert lltype.typeOf(value) == self.TYPE
  495. return value
  496. def write_into_ptr(self, ptr, value):
  497. ptr[0] = value
  498. class _signed_fakeaccessor(_fakeaccessor):
  499. TYPE = lltype.Signed
  500. class _float_fakeaccessor(_fakeaccessor):
  501. TYPE = lltype.Float
  502. class _char_fakeaccessor(_fakeaccessor):
  503. TYPE = lltype.Char
  504. class _address_fakeaccessor(_fakeaccessor):
  505. TYPE = Address
  506. def read_from_ptr(self, ptr):
  507. value = ptr[0]
  508. if isinstance(value, lltype._ptr):
  509. return value._cast_to_adr()
  510. elif lltype.typeOf(value) == Address:
  511. return value
  512. else:
  513. raise TypeError(value)
  514. def write_into_ptr(self, ptr, value):
  515. TARGETTYPE = lltype.typeOf(ptr).TO.OF
  516. if TARGETTYPE == Address:
  517. pass
  518. elif isinstance(TARGETTYPE, lltype.Ptr):
  519. value = cast_adr_to_ptr(value, TARGETTYPE)
  520. else:
  521. raise TypeError(TARGETTYPE)
  522. ptr[0] = value
  523. supported_access_types = {"signed": lltype.Signed,
  524. "unsigned": lltype.Unsigned,
  525. "char": lltype.Char,
  526. "address": Address,
  527. "float": lltype.Float,
  528. }
  529. fakeaddress.signed = property(_signed_fakeaccessor)
  530. fakeaddress.float = property(_float_fakeaccessor)
  531. fakeaddress.char = property(_char_fakeaccessor)
  532. fakeaddress.address = property(_address_fakeaccessor)
  533. fakeaddress._TYPE = Address
  534. # the obtained address will not keep the object alive. e.g. if the object is
  535. # only reachable through an address, it might get collected
  536. def cast_ptr_to_adr(obj):
  537. assert isinstance(lltype.typeOf(obj), lltype.Ptr)
  538. return obj._cast_to_adr()
  539. def cast_adr_to_ptr(adr, EXPECTED_TYPE):
  540. return adr._cast_to_ptr(EXPECTED_TYPE)
  541. def cast_adr_to_int(adr, mode="emulated"):
  542. # The following modes are supported before translation (after
  543. # translation, it's all just a cast):
  544. # * mode="emulated": goes via lltype.cast_ptr_to_int(), which returns some
  545. # number based on id(). The difference is that it works even if the
  546. # address is that of a dead object.
  547. # * mode="symbolic": returns an AddressAsInt instance, which can only be
  548. # cast back to an address later.
  549. # * mode="forced": uses rffi.cast() to return a real number.
  550. assert mode in ("emulated", "symbolic", "forced")
  551. res = adr._cast_to_int(symbolic = (mode != "emulated"))
  552. if mode == "forced":
  553. from pypy.rpython.lltypesystem.rffi import cast
  554. res = cast(lltype.Signed, res)
  555. return res
  556. _NONGCREF = lltype.Ptr(lltype.OpaqueType('NONGCREF'))
  557. def cast_int_to_adr(int):
  558. if isinstance(int, AddressAsInt):
  559. return int.adr
  560. try:
  561. ptr = lltype.cast_int_to_ptr(_NONGCREF, int)
  562. except ValueError:
  563. from pypy.rpython.lltypesystem import ll2ctypes
  564. ptr = ll2ctypes._int2obj[int]._as_ptr()
  565. return cast_ptr_to_adr(ptr)
  566. # ____________________________________________________________
  567. # Weakrefs.
  568. #
  569. # An object of type WeakRef is a small GC-managed object that contains
  570. # a weak reference to another GC-managed object, as in regular Python.
  571. #
  572. class _WeakRefType(lltype.ContainerType):
  573. _gckind = 'gc'
  574. def __str__(self):
  575. return "WeakRef"
  576. WeakRef = _WeakRefType()
  577. WeakRefPtr = lltype.Ptr(WeakRef)
  578. def weakref_create(ptarget):
  579. # ptarget should not be a nullptr
  580. PTRTYPE = lltype.typeOf(ptarget)
  581. assert isinstance(PTRTYPE, lltype.Ptr)
  582. assert PTRTYPE.TO._gckind == 'gc'
  583. assert ptarget
  584. return _wref(ptarget)._as_ptr()
  585. def weakref_deref(PTRTYPE, pwref):
  586. # pwref should not be a nullptr
  587. assert isinstance(PTRTYPE, lltype.Ptr)
  588. assert PTRTYPE.TO._gckind == 'gc'
  589. assert lltype.typeOf(pwref) == WeakRefPtr
  590. p = pwref._obj._dereference()
  591. if p is None:
  592. return lltype.nullptr(PTRTYPE.TO)
  593. else:
  594. return cast_any_ptr(PTRTYPE, p)
  595. class _wref(lltype._container):
  596. _gckind = 'gc'
  597. _TYPE = WeakRef
  598. def __init__(self, ptarget):
  599. if ptarget is None:
  600. self._obref = lambda: None
  601. else:
  602. obj = lltype.normalizeptr(ptarget)._obj
  603. self._obref = weakref.ref(obj)
  604. def _dereference(self):
  605. obj = self._obref()
  606. # in combination with a GC like the SemiSpace, the 'obj' can be
  607. # still alive in the CPython sense but freed by the arena logic.
  608. if obj is None or obj._was_freed():
  609. return None
  610. else:
  611. return obj._as_ptr()
  612. def __repr__(self):
  613. return '<%s>' % (self,)
  614. def __str__(self):
  615. return 'wref -> %s' % (self._obref(),)
  616. # a prebuilt pointer to a dead low-level weakref
  617. dead_wref = _wref(None)._as_ptr()
  618. # The rest is to support the GC transformers: they can use it to build
  619. # an explicit weakref object with some structure and then "hide" the
  620. # result by casting it to a WeakRefPtr, and "reveal" it again. In other
  621. # words, weakref_create and weakref_deref are operations that exist only
  622. # before the GC transformation, whereas the two cast operations below
  623. # exist only after. They are implemented here only to allow GC
  624. # transformers to be tested on top of the llinterpreter.
  625. def cast_ptr_to_weakrefptr(ptr):
  626. if ptr:
  627. return _gctransformed_wref(ptr)._as_ptr()
  628. else:
  629. return lltype.nullptr(WeakRef)
  630. def cast_weakrefptr_to_ptr(PTRTYPE, pwref):
  631. assert lltype.typeOf(pwref) == WeakRefPtr
  632. if pwref:
  633. assert isinstance(pwref._obj, _gctransformed_wref)
  634. if PTRTYPE is not None:
  635. assert PTRTYPE == lltype.typeOf(pwref._obj._ptr)
  636. return pwref._obj._ptr
  637. else:
  638. return lltype.nullptr(PTRTYPE.TO)
  639. class _gctransformed_wref(lltype._container):
  640. _gckind = 'gc'
  641. _TYPE = WeakRef
  642. def __init__(self, ptr):
  643. self._ptr = ptr
  644. def __repr__(self):
  645. return '<%s>' % (self,)
  646. def __str__(self):
  647. return 'gctransformed_wref(%s)' % (self._ptr,)
  648. def _normalizedcontainer(self, check=True):
  649. return self._ptr._getobj(check=check)._normalizedcontainer(check=check)
  650. def _was_freed(self):
  651. return self._ptr._was_freed()
  652. # ____________________________________________________________
  653. def raw_malloc(size):
  654. if not isinstance(size, AddressOffset):
  655. raise NotImplementedError(size)
  656. return size._raw_malloc([], zero=False)
  657. def raw_free(adr):
  658. # try to free the whole object if 'adr' is the address of the header
  659. from pypy.rpython.memory.gcheader import GCHeaderBuilder
  660. try:
  661. objectptr = GCHeaderBuilder.object_from_header(adr.ptr)
  662. except KeyError:
  663. pass
  664. else:
  665. raw_free(cast_ptr_to_adr(objectptr))
  666. assert isinstance(adr.ref()._obj, lltype._parentable)
  667. adr.ptr._as_obj()._free()
  668. def raw_malloc_usage(size):
  669. if isinstance(size, AddressOffset):
  670. # ouah
  671. from pypy.rpython.memory.lltypelayout import convert_offset_to_int
  672. size = convert_offset_to_int(size)
  673. return size
  674. def raw_memclear(adr, size):
  675. if not isinstance(size, AddressOffset):
  676. raise NotImplementedError(size)
  677. assert lltype.typeOf(adr) == Address
  678. zeroadr = size._raw_malloc([], zero=True)
  679. size.raw_memcopy(zeroadr, adr)
  680. def raw_memcopy(source, dest, size):
  681. assert lltype.typeOf(source) == Address
  682. assert lltype.typeOf(dest) == Address
  683. size.raw_memcopy(source, dest)
  684. def raw_memmove(source, dest, size):
  685. # for now let's assume that raw_memmove is the same as raw_memcopy,
  686. # when run on top of fake addresses, but we _free the source object
  687. raw_memcopy(source, dest, size)
  688. source.ptr._as_obj()._free()
  689. def cast_any_ptr(EXPECTED_TYPE, ptr):
  690. # this is a generalization of the various cast_xxx_ptr() functions.
  691. PTRTYPE = lltype.typeOf(ptr)
  692. if PTRTYPE == EXPECTED_TYPE:
  693. return ptr
  694. elif EXPECTED_TYPE == WeakRefPtr:
  695. return cast_ptr_to_weakrefptr(ptr)
  696. elif PTRTYPE == WeakRefPtr:
  697. ptr = cast_weakrefptr_to_ptr(None, ptr)
  698. return cast_any_ptr(EXPECTED_TYPE, ptr)
  699. elif (isinstance(EXPECTED_TYPE.TO, lltype.OpaqueType) or
  700. isinstance(PTRTYPE.TO, lltype.OpaqueType)):
  701. return lltype.cast_opaque_ptr(EXPECTED_TYPE, ptr)
  702. else:
  703. # regular case
  704. return lltype.cast_pointer(EXPECTED_TYPE, ptr)
  705. def _reccopy(source, dest):
  706. # copy recursively a structure or array onto another.
  707. T = lltype.typeOf(source).TO
  708. assert T == lltype.typeOf(dest).TO
  709. if isinstance(T, (lltype.Array, lltype.FixedSizeArray)):
  710. sourcelgt = source._obj.getlength()
  711. destlgt = dest._obj.getlength()
  712. lgt = min(sourcelgt, destlgt)
  713. ITEMTYPE = T.OF
  714. for i in range(lgt):
  715. if isinstance(ITEMTYPE, lltype.ContainerType):
  716. subsrc = source._obj.getitem(i)._as_ptr()
  717. subdst = dest._obj.getitem(i)._as_ptr()
  718. _reccopy(subsrc, subdst)
  719. else:
  720. # this is a hack XXX de-hack this
  721. llvalue = source._obj.getitem(i, uninitialized_ok=True)
  722. dest._obj.setitem(i, llvalue)
  723. elif isinstance(T, lltype.Struct):
  724. for name in T._names:
  725. FIELDTYPE = getattr(T, name)
  726. if isinstance(FIELDTYPE, lltype.ContainerType):
  727. subsrc = source._obj._getattr(name)._as_ptr()
  728. subdst = dest._obj._getattr(name)._as_ptr()
  729. _reccopy(subsrc, subdst)
  730. else:
  731. # this is a hack XXX de-hack this
  732. llvalue = source._obj._getattr(name, uninitialized_ok=True)
  733. setattr(dest._obj, name, llvalue)
  734. else:
  735. raise TypeError(T)
  736. from pypy.rpython.extregistry import ExtRegistryEntry
  737. class RawMemmoveEntry(ExtRegistryEntry):
  738. _about_ = raw_memmove
  739. def compute_result_annotation(self, s_from, s_to, s_size):
  740. from pypy.annotation.model import SomeAddress, SomeInteger
  741. assert isinstance(s_from, SomeAddress)
  742. assert isinstance(s_to, SomeAddress)
  743. assert isinstance(s_size, SomeInteger)
  744. def specialize_call(self, hop):
  745. hop.exception_cannot_occur()
  746. v_list = hop.inputargs(Address, Address, lltype.Signed)
  747. return hop.genop('raw_memmove', v_list)