PageRenderTime 51ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/pypy/jit/codewriter/support.py

https://bitbucket.org/pypy/pypy/
Python | 891 lines | 695 code | 159 blank | 37 comment | 76 complexity | 893a771a6336887c8555dd4f9d6cf771 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. import sys
  2. from pypy.rpython.lltypesystem import lltype, rclass, rffi
  3. from pypy.rpython.ootypesystem import ootype
  4. from pypy.rpython import rlist
  5. from pypy.rpython.lltypesystem import rstr as ll_rstr, rdict as ll_rdict
  6. from pypy.rpython.lltypesystem import rlist as lltypesystem_rlist
  7. from pypy.rpython.lltypesystem.module import ll_math
  8. from pypy.rpython.lltypesystem.lloperation import llop
  9. from pypy.rpython.ootypesystem import rdict as oo_rdict
  10. from pypy.rpython.llinterp import LLInterpreter
  11. from pypy.rpython.extregistry import ExtRegistryEntry
  12. from pypy.rpython.annlowlevel import cast_base_ptr_to_instance
  13. from pypy.translator.simplify import get_funcobj
  14. from pypy.translator.unsimplify import split_block
  15. from pypy.objspace.flow.model import Constant
  16. from pypy.translator.translator import TranslationContext
  17. from pypy.annotation.policy import AnnotatorPolicy
  18. from pypy.annotation import model as annmodel
  19. from pypy.rpython.annlowlevel import MixLevelHelperAnnotator
  20. from pypy.jit.metainterp.typesystem import deref
  21. from pypy.rlib import rgc
  22. from pypy.rlib.jit import elidable
  23. from pypy.rlib.rarithmetic import r_longlong, r_ulonglong, r_uint, intmask
  24. def getargtypes(annotator, values):
  25. if values is None: # for backend tests producing stand-alone exe's
  26. from pypy.annotation.listdef import s_list_of_strings
  27. return [s_list_of_strings]
  28. return [_annotation(annotator, x) for x in values]
  29. def _annotation(a, x):
  30. T = lltype.typeOf(x)
  31. if T == lltype.Ptr(ll_rstr.STR):
  32. t = str
  33. else:
  34. t = annmodel.lltype_to_annotation(T)
  35. return a.typeannotation(t)
  36. def annotate(func, values, inline=None, backendoptimize=True,
  37. type_system="lltype", translationoptions={}):
  38. # build the normal ll graphs for ll_function
  39. t = TranslationContext()
  40. for key, value in translationoptions.items():
  41. setattr(t.config.translation, key, value)
  42. annpolicy = AnnotatorPolicy()
  43. annpolicy.allow_someobjects = False
  44. a = t.buildannotator(policy=annpolicy)
  45. argtypes = getargtypes(a, values)
  46. a.build_types(func, argtypes, main_entry_point=True)
  47. rtyper = t.buildrtyper(type_system = type_system)
  48. rtyper.specialize()
  49. #if inline:
  50. # auto_inlining(t, threshold=inline)
  51. if backendoptimize:
  52. from pypy.translator.backendopt.all import backend_optimizations
  53. backend_optimizations(t, inline_threshold=inline or 0,
  54. remove_asserts=True, really_remove_asserts=True)
  55. return rtyper
  56. def getgraph(func, values):
  57. rtyper = annotate(func, values)
  58. return rtyper.annotator.translator.graphs[0]
  59. def split_before_jit_merge_point(graph, portalblock, portalopindex):
  60. """Split the block just before the 'jit_merge_point',
  61. making sure the input args are in the canonical order.
  62. """
  63. # split the block just before the jit_merge_point()
  64. if portalopindex > 0:
  65. link = split_block(None, portalblock, portalopindex)
  66. portalblock = link.target
  67. portalop = portalblock.operations[0]
  68. # split again, this time enforcing the order of the live vars
  69. # specified by decode_hp_hint_args().
  70. assert portalop.opname == 'jit_marker'
  71. assert portalop.args[0].value == 'jit_merge_point'
  72. greens_v, reds_v = decode_hp_hint_args(portalop)
  73. link = split_block(None, portalblock, 0, greens_v + reds_v)
  74. return link.target
  75. def decode_hp_hint_args(op):
  76. # Returns (list-of-green-vars, list-of-red-vars) without Voids.
  77. # Both lists must be sorted: first INT, then REF, then FLOAT.
  78. assert op.opname == 'jit_marker'
  79. jitdriver = op.args[1].value
  80. numgreens = len(jitdriver.greens)
  81. numreds = len(jitdriver.reds)
  82. greens_v = op.args[2:2+numgreens]
  83. reds_v = op.args[2+numgreens:]
  84. assert len(reds_v) == numreds
  85. #
  86. def _sort(args_v, is_green):
  87. from pypy.jit.metainterp.history import getkind
  88. lst = [v for v in args_v if v.concretetype is not lltype.Void]
  89. if is_green:
  90. assert len(lst) == len(args_v), (
  91. "not supported so far: 'greens' variables contain Void")
  92. _kind2count = {'int': 1, 'ref': 2, 'float': 3}
  93. lst2 = sorted(lst, key=lambda v: _kind2count[getkind(v.concretetype)])
  94. # a crash here means that you have to reorder the variable named in
  95. # the JitDriver. Indeed, greens and reds must both be sorted: first
  96. # all INTs, followed by all REFs, followed by all FLOATs.
  97. assert lst == lst2
  98. return lst
  99. #
  100. return (_sort(greens_v, True), _sort(reds_v, False))
  101. def maybe_on_top_of_llinterp(rtyper, fnptr):
  102. # Run a generated graph on top of the llinterp for testing.
  103. # When translated, this just returns the fnptr.
  104. funcobj = get_funcobj(fnptr)
  105. if hasattr(funcobj, 'graph'):
  106. llinterp = LLInterpreter(rtyper) #, exc_data_ptr=exc_data_ptr)
  107. def on_top_of_llinterp(*args):
  108. return llinterp.eval_graph(funcobj.graph, list(args))
  109. else:
  110. assert hasattr(funcobj, '_callable')
  111. def on_top_of_llinterp(*args):
  112. return funcobj._callable(*args)
  113. return on_top_of_llinterp
  114. class Entry(ExtRegistryEntry):
  115. _about_ = maybe_on_top_of_llinterp
  116. def compute_result_annotation(self, s_rtyper, s_fnptr):
  117. return s_fnptr
  118. def specialize_call(self, hop):
  119. hop.exception_cannot_occur()
  120. return hop.inputarg(hop.args_r[1], arg=1)
  121. # ____________________________________________________________
  122. #
  123. # Manually map oopspec'ed operations back to their ll implementation
  124. # coming from modules like pypy.rpython.rlist. The following
  125. # functions are fished from the globals() by setup_extra_builtin().
  126. def _ll_0_newlist(LIST):
  127. return LIST.ll_newlist(0)
  128. def _ll_1_newlist(LIST, count):
  129. return LIST.ll_newlist(count)
  130. def _ll_2_newlist(LIST, count, item):
  131. return rlist.ll_alloc_and_set(LIST, count, item)
  132. _ll_0_newlist.need_result_type = True
  133. _ll_1_newlist.need_result_type = True
  134. _ll_2_newlist.need_result_type = True
  135. def _ll_1_list_len(l):
  136. return l.ll_length()
  137. def _ll_2_list_getitem(l, index):
  138. return rlist.ll_getitem(rlist.dum_checkidx, l, index)
  139. def _ll_3_list_setitem(l, index, newitem):
  140. rlist.ll_setitem(rlist.dum_checkidx, l, index, newitem)
  141. def _ll_2_list_delitem(l, index):
  142. rlist.ll_delitem(rlist.dum_checkidx, l, index)
  143. def _ll_1_list_pop(l):
  144. return rlist.ll_pop_default(rlist.dum_checkidx, l)
  145. def _ll_2_list_pop(l, index):
  146. return rlist.ll_pop(rlist.dum_checkidx, l, index)
  147. _ll_2_list_append = rlist.ll_append
  148. _ll_2_list_extend = rlist.ll_extend
  149. _ll_3_list_insert = rlist.ll_insert_nonneg
  150. _ll_4_list_setslice = rlist.ll_listsetslice
  151. _ll_2_list_delslice_startonly = rlist.ll_listdelslice_startonly
  152. _ll_3_list_delslice_startstop = rlist.ll_listdelslice_startstop
  153. _ll_2_list_inplace_mul = rlist.ll_inplace_mul
  154. _ll_2_list_getitem_foldable = _ll_2_list_getitem
  155. _ll_1_list_len_foldable = _ll_1_list_len
  156. _ll_5_list_ll_arraycopy = rgc.ll_arraycopy
  157. @elidable
  158. def _ll_1_gc_identityhash(x):
  159. return lltype.identityhash(x)
  160. # the following function should not be "@elidable": I can think of
  161. # a corner case in which id(const) is constant-folded, and then 'const'
  162. # disappears and is collected too early (possibly causing another object
  163. # with the same id() to appear).
  164. def _ll_1_gc_id(ptr):
  165. return llop.gc_id(lltype.Signed, ptr)
  166. def _ll_1_jit_force_virtual(inst):
  167. return llop.jit_force_virtual(lltype.typeOf(inst), inst)
  168. def _ll_2_int_floordiv_ovf_zer(x, y):
  169. if y == 0:
  170. raise ZeroDivisionError
  171. if x == -sys.maxint - 1 and y == -1:
  172. raise OverflowError
  173. return llop.int_floordiv(lltype.Signed, x, y)
  174. def _ll_2_int_floordiv_ovf(x, y):
  175. if x == -sys.maxint - 1 and y == -1:
  176. raise OverflowError
  177. return llop.int_floordiv(lltype.Signed, x, y)
  178. def _ll_2_int_floordiv_zer(x, y):
  179. if y == 0:
  180. raise ZeroDivisionError
  181. return llop.int_floordiv(lltype.Signed, x, y)
  182. def _ll_2_int_mod_ovf_zer(x, y):
  183. if y == 0:
  184. raise ZeroDivisionError
  185. if x == -sys.maxint - 1 and y == -1:
  186. raise OverflowError
  187. return llop.int_mod(lltype.Signed, x, y)
  188. def _ll_2_int_mod_ovf(x, y):
  189. if x == -sys.maxint - 1 and y == -1:
  190. raise OverflowError
  191. return llop.int_mod(lltype.Signed, x, y)
  192. def _ll_2_int_mod_zer(x, y):
  193. if y == 0:
  194. raise ZeroDivisionError
  195. return llop.int_mod(lltype.Signed, x, y)
  196. def _ll_2_int_lshift_ovf(x, y):
  197. result = x << y
  198. if (result >> y) != x:
  199. raise OverflowError
  200. return result
  201. def _ll_1_int_abs(x):
  202. if x < 0:
  203. return -x
  204. else:
  205. return x
  206. def _ll_1_cast_uint_to_float(x):
  207. # XXX on 32-bit platforms, this should be done using cast_longlong_to_float
  208. # (which is a residual call right now in the x86 backend)
  209. return llop.cast_uint_to_float(lltype.Float, x)
  210. def _ll_1_cast_float_to_uint(x):
  211. # XXX on 32-bit platforms, this should be done using cast_float_to_longlong
  212. # (which is a residual call right now in the x86 backend)
  213. return llop.cast_float_to_uint(lltype.Unsigned, x)
  214. # math support
  215. # ------------
  216. _ll_1_ll_math_ll_math_sqrt = ll_math.ll_math_sqrt
  217. # long long support
  218. # -----------------
  219. def u_to_longlong(x):
  220. return rffi.cast(lltype.SignedLongLong, x)
  221. def _ll_1_llong_invert(xll):
  222. y = ~r_ulonglong(xll)
  223. return u_to_longlong(y)
  224. def _ll_1_ullong_invert(xull):
  225. return ~xull
  226. def _ll_2_llong_lt(xll, yll):
  227. return xll < yll
  228. def _ll_2_llong_le(xll, yll):
  229. return xll <= yll
  230. def _ll_2_llong_eq(xll, yll):
  231. return xll == yll
  232. def _ll_2_llong_ne(xll, yll):
  233. return xll != yll
  234. def _ll_2_llong_gt(xll, yll):
  235. return xll > yll
  236. def _ll_2_llong_ge(xll, yll):
  237. return xll >= yll
  238. def _ll_2_ullong_eq(xull, yull):
  239. return xull == yull
  240. def _ll_2_ullong_ne(xull, yull):
  241. return xull != yull
  242. def _ll_2_ullong_ult(xull, yull):
  243. return xull < yull
  244. def _ll_2_ullong_ule(xull, yull):
  245. return xull <= yull
  246. def _ll_2_ullong_ugt(xull, yull):
  247. return xull > yull
  248. def _ll_2_ullong_uge(xull, yull):
  249. return xull >= yull
  250. def _ll_2_llong_add(xll, yll):
  251. z = r_ulonglong(xll) + r_ulonglong(yll)
  252. return u_to_longlong(z)
  253. def _ll_2_llong_sub(xll, yll):
  254. z = r_ulonglong(xll) - r_ulonglong(yll)
  255. return u_to_longlong(z)
  256. def _ll_2_llong_mul(xll, yll):
  257. z = r_ulonglong(xll) * r_ulonglong(yll)
  258. return u_to_longlong(z)
  259. def _ll_2_llong_and(xll, yll):
  260. z = r_ulonglong(xll) & r_ulonglong(yll)
  261. return u_to_longlong(z)
  262. def _ll_2_llong_or(xll, yll):
  263. z = r_ulonglong(xll) | r_ulonglong(yll)
  264. return u_to_longlong(z)
  265. def _ll_2_llong_xor(xll, yll):
  266. z = r_ulonglong(xll) ^ r_ulonglong(yll)
  267. return u_to_longlong(z)
  268. def _ll_2_ullong_add(xull, yull):
  269. z = (xull) + (yull)
  270. return (z)
  271. def _ll_2_ullong_sub(xull, yull):
  272. z = (xull) - (yull)
  273. return (z)
  274. def _ll_2_ullong_mul(xull, yull):
  275. z = (xull) * (yull)
  276. return (z)
  277. def _ll_2_ullong_and(xull, yull):
  278. z = (xull) & (yull)
  279. return (z)
  280. def _ll_2_ullong_or(xull, yull):
  281. z = (xull) | (yull)
  282. return (z)
  283. def _ll_2_ullong_xor(xull, yull):
  284. z = (xull) ^ (yull)
  285. return (z)
  286. def _ll_2_llong_lshift(xll, y):
  287. z = r_ulonglong(xll) << y
  288. return u_to_longlong(z)
  289. def _ll_2_ullong_lshift(xull, y):
  290. return xull << y
  291. def _ll_2_llong_rshift(xll, y):
  292. return xll >> y
  293. def _ll_2_ullong_urshift(xull, y):
  294. return xull >> y
  295. def _ll_1_llong_from_int(x):
  296. return r_longlong(intmask(x))
  297. def _ll_1_ullong_from_int(x):
  298. return r_ulonglong(intmask(x))
  299. def _ll_1_llong_from_uint(x):
  300. return r_longlong(r_uint(x))
  301. def _ll_1_ullong_from_uint(x):
  302. return r_ulonglong(r_uint(x))
  303. def _ll_1_llong_to_int(xll):
  304. return intmask(xll)
  305. def _ll_1_llong_from_float(xf):
  306. return r_longlong(xf)
  307. def _ll_1_ullong_from_float(xf):
  308. return r_ulonglong(xf)
  309. def _ll_1_llong_to_float(xll):
  310. return float(rffi.cast(lltype.SignedLongLong, xll))
  311. def _ll_1_ullong_u_to_float(xull):
  312. return float(rffi.cast(lltype.UnsignedLongLong, xull))
  313. def _ll_1_llong_abs(xll):
  314. if xll < 0:
  315. return -xll
  316. else:
  317. return xll
  318. def _ll_2_llong_floordiv(xll, yll):
  319. return llop.llong_floordiv(lltype.SignedLongLong, xll, yll)
  320. def _ll_2_llong_floordiv_zer(xll, yll):
  321. if yll == 0:
  322. raise ZeroDivisionError
  323. return llop.llong_floordiv(lltype.SignedLongLong, xll, yll)
  324. def _ll_2_llong_mod(xll, yll):
  325. return llop.llong_mod(lltype.SignedLongLong, xll, yll)
  326. def _ll_2_llong_mod_zer(xll, yll):
  327. if yll == 0:
  328. raise ZeroDivisionError
  329. return llop.llong_mod(lltype.SignedLongLong, xll, yll)
  330. def _ll_2_ullong_floordiv(xll, yll):
  331. return llop.ullong_floordiv(lltype.UnsignedLongLong, xll, yll)
  332. def _ll_2_ullong_floordiv_zer(xll, yll):
  333. if yll == 0:
  334. raise ZeroDivisionError
  335. return llop.ullong_floordiv(lltype.UnsignedLongLong, xll, yll)
  336. def _ll_2_ullong_mod(xll, yll):
  337. return llop.ullong_mod(lltype.UnsignedLongLong, xll, yll)
  338. def _ll_2_ullong_mod_zer(xll, yll):
  339. if yll == 0:
  340. raise ZeroDivisionError
  341. return llop.ullong_mod(lltype.UnsignedLongLong, xll, yll)
  342. def _ll_2_uint_mod(xll, yll):
  343. return llop.uint_mod(lltype.Unsigned, xll, yll)
  344. # libffi support
  345. # --------------
  346. def func(llfunc):
  347. from pypy.rlib.libffi import Func
  348. return cast_base_ptr_to_instance(Func, llfunc)
  349. def _ll_1_libffi_prepare_call(llfunc):
  350. return func(llfunc)._prepare()
  351. def _ll_4_libffi_push_int(llfunc, value, ll_args, i):
  352. return func(llfunc)._push_int(value, ll_args, i)
  353. def _ll_4_libffi_push_float(llfunc, value, ll_args, i):
  354. return func(llfunc)._push_float(value, ll_args, i)
  355. def _ll_3_libffi_call_int(llfunc, funcsym, ll_args):
  356. return func(llfunc)._do_call(funcsym, ll_args, rffi.LONG)
  357. def _ll_3_libffi_call_float(llfunc, funcsym, ll_args):
  358. return func(llfunc)._do_call(funcsym, ll_args, rffi.DOUBLE)
  359. def _ll_3_libffi_call_void(llfunc, funcsym, ll_args):
  360. return func(llfunc)._do_call(funcsym, ll_args, lltype.Void)
  361. # in the following calls to builtins, the JIT is allowed to look inside:
  362. inline_calls_to = [
  363. ('int_floordiv_ovf_zer', [lltype.Signed, lltype.Signed], lltype.Signed),
  364. ('int_floordiv_ovf', [lltype.Signed, lltype.Signed], lltype.Signed),
  365. ('int_floordiv_zer', [lltype.Signed, lltype.Signed], lltype.Signed),
  366. ('int_mod_ovf_zer', [lltype.Signed, lltype.Signed], lltype.Signed),
  367. ('int_mod_ovf', [lltype.Signed, lltype.Signed], lltype.Signed),
  368. ('int_mod_zer', [lltype.Signed, lltype.Signed], lltype.Signed),
  369. ('int_lshift_ovf', [lltype.Signed, lltype.Signed], lltype.Signed),
  370. ('int_abs', [lltype.Signed], lltype.Signed),
  371. ('ll_math.ll_math_sqrt', [lltype.Float], lltype.Float),
  372. ]
  373. class LLtypeHelpers:
  374. # ---------- dict ----------
  375. def _ll_0_newdict(DICT):
  376. return ll_rdict.ll_newdict(DICT)
  377. _ll_0_newdict.need_result_type = True
  378. _ll_2_dict_delitem = ll_rdict.ll_dict_delitem
  379. _ll_1_dict_copy = ll_rdict.ll_copy
  380. _ll_1_dict_clear = ll_rdict.ll_clear
  381. _ll_2_dict_update = ll_rdict.ll_update
  382. # ---------- dict keys(), values(), items(), iter ----------
  383. _ll_1_dict_keys = ll_rdict.ll_dict_keys
  384. _ll_1_dict_values = ll_rdict.ll_dict_values
  385. _ll_1_dict_items = ll_rdict.ll_dict_items
  386. _ll_1_dict_keys .need_result_type = True
  387. _ll_1_dict_values.need_result_type = True
  388. _ll_1_dict_items .need_result_type = True
  389. _dictnext_keys = staticmethod(ll_rdict.ll_dictnext_group['keys'])
  390. _dictnext_values = staticmethod(ll_rdict.ll_dictnext_group['values'])
  391. _dictnext_items = staticmethod(ll_rdict.ll_dictnext_group['items'])
  392. def _ll_1_dictiter_nextkeys(iter):
  393. return LLtypeHelpers._dictnext_keys(None, iter)
  394. def _ll_1_dictiter_nextvalues(iter):
  395. return LLtypeHelpers._dictnext_values(None, iter)
  396. def _ll_1_dictiter_nextitems(RES, iter):
  397. return LLtypeHelpers._dictnext_items(lltype.Ptr(RES), iter)
  398. _ll_1_dictiter_nextitems.need_result_type = True
  399. _ll_1_dict_resize = ll_rdict.ll_dict_resize
  400. # ---------- strings and unicode ----------
  401. _ll_1_str_str2unicode = ll_rstr.LLHelpers.ll_str2unicode
  402. def _ll_4_str_eq_slice_checknull(s1, start, length, s2):
  403. """str1[start : start + length] == str2."""
  404. if not s2:
  405. return 0
  406. chars2 = s2.chars
  407. if len(chars2) != length:
  408. return 0
  409. j = 0
  410. chars1 = s1.chars
  411. while j < length:
  412. if chars1[start + j] != chars2[j]:
  413. return 0
  414. j += 1
  415. return 1
  416. def _ll_4_str_eq_slice_nonnull(s1, start, length, s2):
  417. """str1[start : start + length] == str2, assuming str2 != NULL."""
  418. chars2 = s2.chars
  419. if len(chars2) != length:
  420. return 0
  421. j = 0
  422. chars1 = s1.chars
  423. while j < length:
  424. if chars1[start + j] != chars2[j]:
  425. return 0
  426. j += 1
  427. return 1
  428. def _ll_4_str_eq_slice_char(s1, start, length, c2):
  429. """str1[start : start + length] == c2."""
  430. if length != 1:
  431. return 0
  432. if s1.chars[start] != c2:
  433. return 0
  434. return 1
  435. def _ll_2_str_eq_nonnull(s1, s2):
  436. len1 = len(s1.chars)
  437. len2 = len(s2.chars)
  438. if len1 != len2:
  439. return 0
  440. j = 0
  441. chars1 = s1.chars
  442. chars2 = s2.chars
  443. while j < len1:
  444. if chars1[j] != chars2[j]:
  445. return 0
  446. j += 1
  447. return 1
  448. def _ll_2_str_eq_nonnull_char(s1, c2):
  449. chars = s1.chars
  450. if len(chars) != 1:
  451. return 0
  452. if chars[0] != c2:
  453. return 0
  454. return 1
  455. def _ll_2_str_eq_checknull_char(s1, c2):
  456. if not s1:
  457. return 0
  458. chars = s1.chars
  459. if len(chars) != 1:
  460. return 0
  461. if chars[0] != c2:
  462. return 0
  463. return 1
  464. def _ll_2_str_eq_lengthok(s1, s2):
  465. j = 0
  466. chars1 = s1.chars
  467. chars2 = s2.chars
  468. len1 = len(chars1)
  469. while j < len1:
  470. if chars1[j] != chars2[j]:
  471. return 0
  472. j += 1
  473. return 1
  474. # ---------- malloc with del ----------
  475. def _ll_2_raw_malloc(TP, size):
  476. return lltype.malloc(TP, size, flavor='raw')
  477. def build_ll_0_alloc_with_del(RESULT, vtable):
  478. def _ll_0_alloc_with_del():
  479. p = lltype.malloc(RESULT.TO)
  480. lltype.cast_pointer(rclass.OBJECTPTR, p).typeptr = vtable
  481. return p
  482. return _ll_0_alloc_with_del
  483. def build_raw_malloc_varsize_builder(zero=False,
  484. add_memory_pressure=False,
  485. track_allocation=True):
  486. def build_ll_1_raw_malloc_varsize(ARRAY):
  487. def _ll_1_raw_malloc_varsize(n):
  488. return lltype.malloc(ARRAY, n, flavor='raw', zero=zero,
  489. add_memory_pressure=add_memory_pressure,
  490. track_allocation=track_allocation)
  491. return _ll_1_raw_malloc_varsize
  492. return build_ll_1_raw_malloc_varsize
  493. build_ll_1_raw_malloc_varsize = (
  494. build_raw_malloc_varsize_builder())
  495. build_ll_1_raw_malloc_varsize_zero = (
  496. build_raw_malloc_varsize_builder(zero=True))
  497. build_ll_1_raw_malloc_varsize_zero_add_memory_pressure = (
  498. build_raw_malloc_varsize_builder(zero=True, add_memory_pressure=True))
  499. build_ll_1_raw_malloc_varsize_add_memory_pressure = (
  500. build_raw_malloc_varsize_builder(add_memory_pressure=True))
  501. build_ll_1_raw_malloc_varsize_no_track_allocation = (
  502. build_raw_malloc_varsize_builder(track_allocation=False))
  503. build_ll_1_raw_malloc_varsize_zero_no_track_allocation = (
  504. build_raw_malloc_varsize_builder(zero=True, track_allocation=False))
  505. build_ll_1_raw_malloc_varsize_zero_add_memory_pressure_no_track_allocation = (
  506. build_raw_malloc_varsize_builder(zero=True, add_memory_pressure=True, track_allocation=False))
  507. build_ll_1_raw_malloc_varsize_add_memory_pressure_no_track_allocation = (
  508. build_raw_malloc_varsize_builder(add_memory_pressure=True, track_allocation=False))
  509. def build_raw_malloc_fixedsize_builder(zero=False,
  510. add_memory_pressure=False,
  511. track_allocation=True):
  512. def build_ll_0_raw_malloc_fixedsize(STRUCT):
  513. def _ll_0_raw_malloc_fixedsize():
  514. return lltype.malloc(STRUCT, flavor='raw', zero=zero,
  515. add_memory_pressure=add_memory_pressure,
  516. track_allocation=track_allocation)
  517. return _ll_0_raw_malloc_fixedsize
  518. return build_ll_0_raw_malloc_fixedsize
  519. build_ll_0_raw_malloc_fixedsize = (
  520. build_raw_malloc_fixedsize_builder())
  521. build_ll_0_raw_malloc_fixedsize_zero = (
  522. build_raw_malloc_fixedsize_builder(zero=True))
  523. build_ll_0_raw_malloc_fixedsize_zero_add_memory_pressure = (
  524. build_raw_malloc_fixedsize_builder(zero=True, add_memory_pressure=True))
  525. build_ll_0_raw_malloc_fixedsize_add_memory_pressure = (
  526. build_raw_malloc_fixedsize_builder(add_memory_pressure=True))
  527. build_ll_0_raw_malloc_fixedsize_no_track_allocation = (
  528. build_raw_malloc_fixedsize_builder(track_allocation=False))
  529. build_ll_0_raw_malloc_fixedsize_zero_no_track_allocation = (
  530. build_raw_malloc_fixedsize_builder(zero=True, track_allocation=False))
  531. build_ll_0_raw_malloc_fixedsize_zero_add_memory_pressure_no_track_allocation = (
  532. build_raw_malloc_fixedsize_builder(zero=True, add_memory_pressure=True, track_allocation=False))
  533. build_ll_0_raw_malloc_fixedsize_add_memory_pressure_no_track_allocation = (
  534. build_raw_malloc_fixedsize_builder(add_memory_pressure=True, track_allocation=False))
  535. def build_raw_free_builder(track_allocation=True):
  536. def build_ll_1_raw_free(ARRAY):
  537. def _ll_1_raw_free(p):
  538. lltype.free(p, flavor='raw',
  539. track_allocation=track_allocation)
  540. return _ll_1_raw_free
  541. return build_ll_1_raw_free
  542. build_ll_1_raw_free = (
  543. build_raw_free_builder())
  544. build_ll_1_raw_free_no_track_allocation = (
  545. build_raw_free_builder(track_allocation=False))
  546. class OOtypeHelpers:
  547. # ---------- dict ----------
  548. def _ll_0_newdict(DICT):
  549. return oo_rdict.ll_newdict(DICT)
  550. _ll_0_newdict.need_result_type = True
  551. def _ll_3_dict_setitem(d, key, value):
  552. d.ll_set(key, value)
  553. def _ll_2_dict_contains(d, key):
  554. return d.ll_contains(key)
  555. def _ll_1_dict_clear(d):
  556. d.ll_clear()
  557. _ll_2_dict_getitem = oo_rdict.ll_dict_getitem
  558. _ll_2_dict_delitem = oo_rdict.ll_dict_delitem
  559. _ll_3_dict_setdefault = oo_rdict.ll_dict_setdefault
  560. _ll_3_dict_get = oo_rdict.ll_dict_get
  561. _ll_1_dict_copy = oo_rdict.ll_dict_copy
  562. _ll_2_dict_update = oo_rdict.ll_dict_update
  563. # ---------- dict keys(), values(), items(), iter ----------
  564. _ll_1_dict_keys = oo_rdict.ll_dict_keys
  565. _ll_1_dict_values = oo_rdict.ll_dict_values
  566. _ll_1_dict_items = oo_rdict.ll_dict_items
  567. _ll_1_dict_keys .need_result_type = True
  568. _ll_1_dict_values.need_result_type = True
  569. _ll_1_dict_items .need_result_type = True
  570. _dictnext_keys = staticmethod(oo_rdict.ll_dictnext_group['keys'])
  571. _dictnext_values = staticmethod(oo_rdict.ll_dictnext_group['values'])
  572. _dictnext_items = staticmethod(oo_rdict.ll_dictnext_group['items'])
  573. def _ll_1_dictiter_nextkeys(iter):
  574. return OOtypeHelpers._dictnext_keys(None, iter)
  575. def _ll_1_dictiter_nextvalues(iter):
  576. return OOtypeHelpers._dictnext_values(None, iter)
  577. def _ll_1_dictiter_nextitems(RES, iter):
  578. return OOtypeHelpers._dictnext_items(RES, iter)
  579. _ll_1_dictiter_nextitems.need_result_type = True
  580. # --------------- oostring and oounicode ----------------
  581. def _ll_2_oostring_signed_foldable(n, base):
  582. return ootype.oostring(n, base)
  583. def _ll_1_oostring_char_foldable(ch):
  584. return ootype.oostring(ch, -1)
  585. def _ll_1_oostring_unsigned_foldable(n):
  586. return ootype.oostring(n, -1)
  587. def _ll_1_oostring_string_foldable(s):
  588. return ootype.oostring(s, -1)
  589. def _ll_1_oostring_root_foldable(s):
  590. return ootype.oostring(s, -1)
  591. def _ll_2_oounicode_signed_foldable(n, base):
  592. return ootype.oounicode(n, base)
  593. def _ll_1_oounicode_unichar_foldable(ch):
  594. return ootype.oounicode(ch, -1)
  595. def _ll_1_oounicode_string_foldable(s):
  596. return ootype.oounicode(s, -1)
  597. # -------------------------------------------------------
  598. def setup_extra_builtin(rtyper, oopspec_name, nb_args, extra=None):
  599. name = '_ll_%d_%s' % (nb_args, oopspec_name.replace('.', '_'))
  600. if extra is not None:
  601. name = 'build' + name
  602. try:
  603. wrapper = globals()[name]
  604. except KeyError:
  605. if rtyper.type_system.name == 'lltypesystem':
  606. Helpers = LLtypeHelpers
  607. else:
  608. Helpers = OOtypeHelpers
  609. wrapper = getattr(Helpers, name).im_func
  610. if extra is not None:
  611. wrapper = wrapper(*extra)
  612. return wrapper
  613. # # ____________________________________________________________
  614. class Index:
  615. def __init__(self, n):
  616. self.n = n
  617. def parse_oopspec(fnobj):
  618. FUNCTYPE = lltype.typeOf(fnobj)
  619. ll_func = fnobj._callable
  620. nb_args = len(FUNCTYPE.ARGS)
  621. argnames = ll_func.func_code.co_varnames[:nb_args]
  622. # parse the oopspec and fill in the arguments
  623. operation_name, args = ll_func.oopspec.split('(', 1)
  624. assert args.endswith(')')
  625. args = args[:-1] + ',' # trailing comma to force tuple syntax
  626. if args.strip() == ',':
  627. args = '()'
  628. nb_args = len(argnames)
  629. argname2index = dict(zip(argnames, [Index(n) for n in range(nb_args)]))
  630. argtuple = eval(args, argname2index)
  631. return operation_name, argtuple
  632. def normalize_opargs(argtuple, opargs):
  633. result = []
  634. for obj in argtuple:
  635. if isinstance(obj, Index):
  636. result.append(opargs[obj.n])
  637. else:
  638. result.append(Constant(obj, lltype.typeOf(obj)))
  639. return result
  640. def get_call_oopspec_opargs(fnobj, opargs):
  641. oopspec, argtuple = parse_oopspec(fnobj)
  642. normalized_opargs = normalize_opargs(argtuple, opargs)
  643. return oopspec, normalized_opargs
  644. def get_oostring_oopspec(op):
  645. T = op.args[0].concretetype
  646. if T is not ootype.Signed:
  647. args = op.args[:-1]
  648. else:
  649. args = op.args
  650. if isinstance(T, ootype.Instance):
  651. T = ootype.ROOT
  652. return '%s_%s_foldable' % (op.opname, T._name.lower()), args
  653. def get_identityhash_oopspec(op):
  654. return 'gc_identityhash', op.args
  655. def get_gcid_oopspec(op):
  656. return 'gc_id', op.args
  657. RENAMED_ADT_NAME = {
  658. 'list': {
  659. 'll_getitem_fast': 'getitem',
  660. 'll_setitem_fast': 'setitem',
  661. 'll_length': 'len',
  662. },
  663. }
  664. def get_send_oopspec(SELFTYPE, name):
  665. oopspec_name = SELFTYPE.oopspec_name
  666. assert oopspec_name is not None
  667. renamed = RENAMED_ADT_NAME.get(oopspec_name, {})
  668. pubname = renamed.get(name, name)
  669. oopspec = '%s.%s' % (oopspec_name, pubname)
  670. return oopspec
  671. def decode_builtin_call(op):
  672. if op.opname == 'oosend':
  673. SELFTYPE, name, opargs = decompose_oosend(op)
  674. return get_send_oopspec(SELFTYPE, name), opargs
  675. elif op.opname == 'direct_call':
  676. fnobj = get_funcobj(op.args[0].value)
  677. opargs = op.args[1:]
  678. return get_call_oopspec_opargs(fnobj, opargs)
  679. elif op.opname in ('oostring', 'oounicode'):
  680. return get_oostring_oopspec(op)
  681. elif op.opname == 'gc_identityhash':
  682. return get_identityhash_oopspec(op)
  683. elif op.opname == 'gc_id':
  684. return get_gcid_oopspec(op)
  685. else:
  686. raise ValueError(op.opname)
  687. def builtin_func_for_spec(rtyper, oopspec_name, ll_args, ll_res,
  688. extra=None, extrakey=None):
  689. assert (extra is None) == (extrakey is None)
  690. key = (oopspec_name, tuple(ll_args), ll_res, extrakey)
  691. try:
  692. return rtyper._builtin_func_for_spec_cache[key]
  693. except (KeyError, AttributeError):
  694. pass
  695. args_s = [annmodel.lltype_to_annotation(v) for v in ll_args]
  696. if '.' not in oopspec_name: # 'newxxx' operations
  697. LIST_OR_DICT = ll_res
  698. else:
  699. LIST_OR_DICT = ll_args[0]
  700. s_result = annmodel.lltype_to_annotation(ll_res)
  701. impl = setup_extra_builtin(rtyper, oopspec_name, len(args_s), extra)
  702. if getattr(impl, 'need_result_type', False):
  703. bk = rtyper.annotator.bookkeeper
  704. args_s.insert(0, annmodel.SomePBC([bk.getdesc(deref(ll_res))]))
  705. #
  706. if hasattr(rtyper, 'annotator'): # regular case
  707. mixlevelann = MixLevelHelperAnnotator(rtyper)
  708. c_func = mixlevelann.constfunc(impl, args_s, s_result)
  709. mixlevelann.finish()
  710. else:
  711. # for testing only
  712. c_func = Constant(oopspec_name,
  713. lltype.Ptr(lltype.FuncType(ll_args, ll_res)))
  714. #
  715. if not hasattr(rtyper, '_builtin_func_for_spec_cache'):
  716. rtyper._builtin_func_for_spec_cache = {}
  717. rtyper._builtin_func_for_spec_cache[key] = (c_func, LIST_OR_DICT)
  718. #
  719. return c_func, LIST_OR_DICT
  720. def decompose_oosend(op):
  721. name = op.args[0].value
  722. opargs = op.args[1:]
  723. SELFTYPE = opargs[0].concretetype
  724. return SELFTYPE, name, opargs
  725. def lookup_oosend_method(op):
  726. SELFTYPE, methname, args_v = decompose_oosend(op)
  727. _, meth = SELFTYPE._lookup(methname)
  728. return SELFTYPE, methname, meth