PageRenderTime 74ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 1ms

/pypy/jit/codewriter/support.py

http://github.com/pypy/pypy
Python | 894 lines | 698 code | 159 blank | 37 comment | 76 complexity | 3759d8e5466f2208bdb3da6ee5b9a17c MD5 | raw file
  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_newlist_hint(LIST, hint):
  136. return LIST.ll_newlist_hint(hint)
  137. _ll_1_newlist_hint.need_result_type = True
  138. def _ll_1_list_len(l):
  139. return l.ll_length()
  140. def _ll_2_list_getitem(l, index):
  141. return rlist.ll_getitem(rlist.dum_checkidx, l, index)
  142. def _ll_3_list_setitem(l, index, newitem):
  143. rlist.ll_setitem(rlist.dum_checkidx, l, index, newitem)
  144. def _ll_2_list_delitem(l, index):
  145. rlist.ll_delitem(rlist.dum_checkidx, l, index)
  146. def _ll_1_list_pop(l):
  147. return rlist.ll_pop_default(rlist.dum_checkidx, l)
  148. def _ll_2_list_pop(l, index):
  149. return rlist.ll_pop(rlist.dum_checkidx, l, index)
  150. _ll_2_list_append = rlist.ll_append
  151. _ll_2_list_extend = rlist.ll_extend
  152. _ll_3_list_insert = rlist.ll_insert_nonneg
  153. _ll_4_list_setslice = rlist.ll_listsetslice
  154. _ll_2_list_delslice_startonly = rlist.ll_listdelslice_startonly
  155. _ll_3_list_delslice_startstop = rlist.ll_listdelslice_startstop
  156. _ll_2_list_inplace_mul = rlist.ll_inplace_mul
  157. _ll_2_list_getitem_foldable = _ll_2_list_getitem
  158. _ll_1_list_len_foldable = _ll_1_list_len
  159. _ll_5_list_ll_arraycopy = rgc.ll_arraycopy
  160. @elidable
  161. def _ll_1_gc_identityhash(x):
  162. return lltype.identityhash(x)
  163. # the following function should not be "@elidable": I can think of
  164. # a corner case in which id(const) is constant-folded, and then 'const'
  165. # disappears and is collected too early (possibly causing another object
  166. # with the same id() to appear).
  167. def _ll_1_gc_id(ptr):
  168. return llop.gc_id(lltype.Signed, ptr)
  169. def _ll_1_jit_force_virtual(inst):
  170. return llop.jit_force_virtual(lltype.typeOf(inst), inst)
  171. def _ll_2_int_floordiv_ovf_zer(x, y):
  172. if y == 0:
  173. raise ZeroDivisionError
  174. if x == -sys.maxint - 1 and y == -1:
  175. raise OverflowError
  176. return llop.int_floordiv(lltype.Signed, x, y)
  177. def _ll_2_int_floordiv_ovf(x, y):
  178. if x == -sys.maxint - 1 and y == -1:
  179. raise OverflowError
  180. return llop.int_floordiv(lltype.Signed, x, y)
  181. def _ll_2_int_floordiv_zer(x, y):
  182. if y == 0:
  183. raise ZeroDivisionError
  184. return llop.int_floordiv(lltype.Signed, x, y)
  185. def _ll_2_int_mod_ovf_zer(x, y):
  186. if y == 0:
  187. raise ZeroDivisionError
  188. if x == -sys.maxint - 1 and y == -1:
  189. raise OverflowError
  190. return llop.int_mod(lltype.Signed, x, y)
  191. def _ll_2_int_mod_ovf(x, y):
  192. if x == -sys.maxint - 1 and y == -1:
  193. raise OverflowError
  194. return llop.int_mod(lltype.Signed, x, y)
  195. def _ll_2_int_mod_zer(x, y):
  196. if y == 0:
  197. raise ZeroDivisionError
  198. return llop.int_mod(lltype.Signed, x, y)
  199. def _ll_2_int_lshift_ovf(x, y):
  200. result = x << y
  201. if (result >> y) != x:
  202. raise OverflowError
  203. return result
  204. def _ll_1_int_abs(x):
  205. if x < 0:
  206. return -x
  207. else:
  208. return x
  209. def _ll_1_cast_uint_to_float(x):
  210. # XXX on 32-bit platforms, this should be done using cast_longlong_to_float
  211. # (which is a residual call right now in the x86 backend)
  212. return llop.cast_uint_to_float(lltype.Float, x)
  213. def _ll_1_cast_float_to_uint(x):
  214. # XXX on 32-bit platforms, this should be done using cast_float_to_longlong
  215. # (which is a residual call right now in the x86 backend)
  216. return llop.cast_float_to_uint(lltype.Unsigned, x)
  217. # math support
  218. # ------------
  219. _ll_1_ll_math_ll_math_sqrt = ll_math.ll_math_sqrt
  220. # long long support
  221. # -----------------
  222. def u_to_longlong(x):
  223. return rffi.cast(lltype.SignedLongLong, x)
  224. def _ll_1_llong_invert(xll):
  225. y = ~r_ulonglong(xll)
  226. return u_to_longlong(y)
  227. def _ll_1_ullong_invert(xull):
  228. return ~xull
  229. def _ll_2_llong_lt(xll, yll):
  230. return xll < yll
  231. def _ll_2_llong_le(xll, yll):
  232. return xll <= yll
  233. def _ll_2_llong_eq(xll, yll):
  234. return xll == yll
  235. def _ll_2_llong_ne(xll, yll):
  236. return xll != yll
  237. def _ll_2_llong_gt(xll, yll):
  238. return xll > yll
  239. def _ll_2_llong_ge(xll, yll):
  240. return xll >= yll
  241. def _ll_2_ullong_eq(xull, yull):
  242. return xull == yull
  243. def _ll_2_ullong_ne(xull, yull):
  244. return xull != yull
  245. def _ll_2_ullong_ult(xull, yull):
  246. return xull < yull
  247. def _ll_2_ullong_ule(xull, yull):
  248. return xull <= yull
  249. def _ll_2_ullong_ugt(xull, yull):
  250. return xull > yull
  251. def _ll_2_ullong_uge(xull, yull):
  252. return xull >= yull
  253. def _ll_2_llong_add(xll, yll):
  254. z = r_ulonglong(xll) + r_ulonglong(yll)
  255. return u_to_longlong(z)
  256. def _ll_2_llong_sub(xll, yll):
  257. z = r_ulonglong(xll) - r_ulonglong(yll)
  258. return u_to_longlong(z)
  259. def _ll_2_llong_mul(xll, yll):
  260. z = r_ulonglong(xll) * r_ulonglong(yll)
  261. return u_to_longlong(z)
  262. def _ll_2_llong_and(xll, yll):
  263. z = r_ulonglong(xll) & r_ulonglong(yll)
  264. return u_to_longlong(z)
  265. def _ll_2_llong_or(xll, yll):
  266. z = r_ulonglong(xll) | r_ulonglong(yll)
  267. return u_to_longlong(z)
  268. def _ll_2_llong_xor(xll, yll):
  269. z = r_ulonglong(xll) ^ r_ulonglong(yll)
  270. return u_to_longlong(z)
  271. def _ll_2_ullong_add(xull, yull):
  272. z = (xull) + (yull)
  273. return (z)
  274. def _ll_2_ullong_sub(xull, yull):
  275. z = (xull) - (yull)
  276. return (z)
  277. def _ll_2_ullong_mul(xull, yull):
  278. z = (xull) * (yull)
  279. return (z)
  280. def _ll_2_ullong_and(xull, yull):
  281. z = (xull) & (yull)
  282. return (z)
  283. def _ll_2_ullong_or(xull, yull):
  284. z = (xull) | (yull)
  285. return (z)
  286. def _ll_2_ullong_xor(xull, yull):
  287. z = (xull) ^ (yull)
  288. return (z)
  289. def _ll_2_llong_lshift(xll, y):
  290. z = r_ulonglong(xll) << y
  291. return u_to_longlong(z)
  292. def _ll_2_ullong_lshift(xull, y):
  293. return xull << y
  294. def _ll_2_llong_rshift(xll, y):
  295. return xll >> y
  296. def _ll_2_ullong_urshift(xull, y):
  297. return xull >> y
  298. def _ll_1_llong_from_int(x):
  299. return r_longlong(intmask(x))
  300. def _ll_1_ullong_from_int(x):
  301. return r_ulonglong(intmask(x))
  302. def _ll_1_llong_from_uint(x):
  303. return r_longlong(r_uint(x))
  304. def _ll_1_ullong_from_uint(x):
  305. return r_ulonglong(r_uint(x))
  306. def _ll_1_llong_to_int(xll):
  307. return intmask(xll)
  308. def _ll_1_llong_from_float(xf):
  309. return r_longlong(xf)
  310. def _ll_1_ullong_from_float(xf):
  311. return r_ulonglong(xf)
  312. def _ll_1_llong_to_float(xll):
  313. return float(rffi.cast(lltype.SignedLongLong, xll))
  314. def _ll_1_ullong_u_to_float(xull):
  315. return float(rffi.cast(lltype.UnsignedLongLong, xull))
  316. def _ll_1_llong_abs(xll):
  317. if xll < 0:
  318. return -xll
  319. else:
  320. return xll
  321. def _ll_2_llong_floordiv(xll, yll):
  322. return llop.llong_floordiv(lltype.SignedLongLong, xll, yll)
  323. def _ll_2_llong_floordiv_zer(xll, yll):
  324. if yll == 0:
  325. raise ZeroDivisionError
  326. return llop.llong_floordiv(lltype.SignedLongLong, xll, yll)
  327. def _ll_2_llong_mod(xll, yll):
  328. return llop.llong_mod(lltype.SignedLongLong, xll, yll)
  329. def _ll_2_llong_mod_zer(xll, yll):
  330. if yll == 0:
  331. raise ZeroDivisionError
  332. return llop.llong_mod(lltype.SignedLongLong, xll, yll)
  333. def _ll_2_ullong_floordiv(xll, yll):
  334. return llop.ullong_floordiv(lltype.UnsignedLongLong, xll, yll)
  335. def _ll_2_ullong_floordiv_zer(xll, yll):
  336. if yll == 0:
  337. raise ZeroDivisionError
  338. return llop.ullong_floordiv(lltype.UnsignedLongLong, xll, yll)
  339. def _ll_2_ullong_mod(xll, yll):
  340. return llop.ullong_mod(lltype.UnsignedLongLong, xll, yll)
  341. def _ll_2_ullong_mod_zer(xll, yll):
  342. if yll == 0:
  343. raise ZeroDivisionError
  344. return llop.ullong_mod(lltype.UnsignedLongLong, xll, yll)
  345. def _ll_2_uint_mod(xll, yll):
  346. return llop.uint_mod(lltype.Unsigned, xll, yll)
  347. # libffi support
  348. # --------------
  349. def func(llfunc):
  350. from pypy.rlib.libffi import Func
  351. return cast_base_ptr_to_instance(Func, llfunc)
  352. def _ll_1_libffi_prepare_call(llfunc):
  353. return func(llfunc)._prepare()
  354. def _ll_4_libffi_push_int(llfunc, value, ll_args, i):
  355. return func(llfunc)._push_int(value, ll_args, i)
  356. def _ll_4_libffi_push_float(llfunc, value, ll_args, i):
  357. return func(llfunc)._push_float(value, ll_args, i)
  358. def _ll_3_libffi_call_int(llfunc, funcsym, ll_args):
  359. return func(llfunc)._do_call(funcsym, ll_args, rffi.LONG)
  360. def _ll_3_libffi_call_float(llfunc, funcsym, ll_args):
  361. return func(llfunc)._do_call(funcsym, ll_args, rffi.DOUBLE)
  362. def _ll_3_libffi_call_void(llfunc, funcsym, ll_args):
  363. return func(llfunc)._do_call(funcsym, ll_args, lltype.Void)
  364. # in the following calls to builtins, the JIT is allowed to look inside:
  365. inline_calls_to = [
  366. ('int_floordiv_ovf_zer', [lltype.Signed, lltype.Signed], lltype.Signed),
  367. ('int_floordiv_ovf', [lltype.Signed, lltype.Signed], lltype.Signed),
  368. ('int_floordiv_zer', [lltype.Signed, lltype.Signed], lltype.Signed),
  369. ('int_mod_ovf_zer', [lltype.Signed, lltype.Signed], lltype.Signed),
  370. ('int_mod_ovf', [lltype.Signed, lltype.Signed], lltype.Signed),
  371. ('int_mod_zer', [lltype.Signed, lltype.Signed], lltype.Signed),
  372. ('int_lshift_ovf', [lltype.Signed, lltype.Signed], lltype.Signed),
  373. ('int_abs', [lltype.Signed], lltype.Signed),
  374. ('ll_math.ll_math_sqrt', [lltype.Float], lltype.Float),
  375. ]
  376. class LLtypeHelpers:
  377. # ---------- dict ----------
  378. def _ll_0_newdict(DICT):
  379. return ll_rdict.ll_newdict(DICT)
  380. _ll_0_newdict.need_result_type = True
  381. _ll_2_dict_delitem = ll_rdict.ll_dict_delitem
  382. _ll_1_dict_copy = ll_rdict.ll_copy
  383. _ll_1_dict_clear = ll_rdict.ll_clear
  384. _ll_2_dict_update = ll_rdict.ll_update
  385. # ---------- dict keys(), values(), items(), iter ----------
  386. _ll_1_dict_keys = ll_rdict.ll_dict_keys
  387. _ll_1_dict_values = ll_rdict.ll_dict_values
  388. _ll_1_dict_items = ll_rdict.ll_dict_items
  389. _ll_1_dict_keys .need_result_type = True
  390. _ll_1_dict_values.need_result_type = True
  391. _ll_1_dict_items .need_result_type = True
  392. _dictnext_keys = staticmethod(ll_rdict.ll_dictnext_group['keys'])
  393. _dictnext_values = staticmethod(ll_rdict.ll_dictnext_group['values'])
  394. _dictnext_items = staticmethod(ll_rdict.ll_dictnext_group['items'])
  395. def _ll_1_dictiter_nextkeys(iter):
  396. return LLtypeHelpers._dictnext_keys(None, iter)
  397. def _ll_1_dictiter_nextvalues(iter):
  398. return LLtypeHelpers._dictnext_values(None, iter)
  399. def _ll_1_dictiter_nextitems(RES, iter):
  400. return LLtypeHelpers._dictnext_items(lltype.Ptr(RES), iter)
  401. _ll_1_dictiter_nextitems.need_result_type = True
  402. _ll_1_dict_resize = ll_rdict.ll_dict_resize
  403. # ---------- strings and unicode ----------
  404. _ll_1_str_str2unicode = ll_rstr.LLHelpers.ll_str2unicode
  405. def _ll_4_str_eq_slice_checknull(s1, start, length, s2):
  406. """str1[start : start + length] == str2."""
  407. if not s2:
  408. return 0
  409. chars2 = s2.chars
  410. if len(chars2) != length:
  411. return 0
  412. j = 0
  413. chars1 = s1.chars
  414. while j < length:
  415. if chars1[start + j] != chars2[j]:
  416. return 0
  417. j += 1
  418. return 1
  419. def _ll_4_str_eq_slice_nonnull(s1, start, length, s2):
  420. """str1[start : start + length] == str2, assuming str2 != NULL."""
  421. chars2 = s2.chars
  422. if len(chars2) != length:
  423. return 0
  424. j = 0
  425. chars1 = s1.chars
  426. while j < length:
  427. if chars1[start + j] != chars2[j]:
  428. return 0
  429. j += 1
  430. return 1
  431. def _ll_4_str_eq_slice_char(s1, start, length, c2):
  432. """str1[start : start + length] == c2."""
  433. if length != 1:
  434. return 0
  435. if s1.chars[start] != c2:
  436. return 0
  437. return 1
  438. def _ll_2_str_eq_nonnull(s1, s2):
  439. len1 = len(s1.chars)
  440. len2 = len(s2.chars)
  441. if len1 != len2:
  442. return 0
  443. j = 0
  444. chars1 = s1.chars
  445. chars2 = s2.chars
  446. while j < len1:
  447. if chars1[j] != chars2[j]:
  448. return 0
  449. j += 1
  450. return 1
  451. def _ll_2_str_eq_nonnull_char(s1, c2):
  452. chars = s1.chars
  453. if len(chars) != 1:
  454. return 0
  455. if chars[0] != c2:
  456. return 0
  457. return 1
  458. def _ll_2_str_eq_checknull_char(s1, c2):
  459. if not s1:
  460. return 0
  461. chars = s1.chars
  462. if len(chars) != 1:
  463. return 0
  464. if chars[0] != c2:
  465. return 0
  466. return 1
  467. def _ll_2_str_eq_lengthok(s1, s2):
  468. j = 0
  469. chars1 = s1.chars
  470. chars2 = s2.chars
  471. len1 = len(chars1)
  472. while j < len1:
  473. if chars1[j] != chars2[j]:
  474. return 0
  475. j += 1
  476. return 1
  477. # ---------- malloc with del ----------
  478. def _ll_2_raw_malloc(TP, size):
  479. return lltype.malloc(TP, size, flavor='raw')
  480. def build_ll_0_alloc_with_del(RESULT, vtable):
  481. def _ll_0_alloc_with_del():
  482. p = lltype.malloc(RESULT.TO)
  483. lltype.cast_pointer(rclass.OBJECTPTR, p).typeptr = vtable
  484. return p
  485. return _ll_0_alloc_with_del
  486. def build_raw_malloc_varsize_builder(zero=False,
  487. add_memory_pressure=False,
  488. track_allocation=True):
  489. def build_ll_1_raw_malloc_varsize(ARRAY):
  490. def _ll_1_raw_malloc_varsize(n):
  491. return lltype.malloc(ARRAY, n, flavor='raw', zero=zero,
  492. add_memory_pressure=add_memory_pressure,
  493. track_allocation=track_allocation)
  494. return _ll_1_raw_malloc_varsize
  495. return build_ll_1_raw_malloc_varsize
  496. build_ll_1_raw_malloc_varsize = (
  497. build_raw_malloc_varsize_builder())
  498. build_ll_1_raw_malloc_varsize_zero = (
  499. build_raw_malloc_varsize_builder(zero=True))
  500. build_ll_1_raw_malloc_varsize_zero_add_memory_pressure = (
  501. build_raw_malloc_varsize_builder(zero=True, add_memory_pressure=True))
  502. build_ll_1_raw_malloc_varsize_add_memory_pressure = (
  503. build_raw_malloc_varsize_builder(add_memory_pressure=True))
  504. build_ll_1_raw_malloc_varsize_no_track_allocation = (
  505. build_raw_malloc_varsize_builder(track_allocation=False))
  506. build_ll_1_raw_malloc_varsize_zero_no_track_allocation = (
  507. build_raw_malloc_varsize_builder(zero=True, track_allocation=False))
  508. build_ll_1_raw_malloc_varsize_zero_add_memory_pressure_no_track_allocation = (
  509. build_raw_malloc_varsize_builder(zero=True, add_memory_pressure=True, track_allocation=False))
  510. build_ll_1_raw_malloc_varsize_add_memory_pressure_no_track_allocation = (
  511. build_raw_malloc_varsize_builder(add_memory_pressure=True, track_allocation=False))
  512. def build_raw_malloc_fixedsize_builder(zero=False,
  513. add_memory_pressure=False,
  514. track_allocation=True):
  515. def build_ll_0_raw_malloc_fixedsize(STRUCT):
  516. def _ll_0_raw_malloc_fixedsize():
  517. return lltype.malloc(STRUCT, flavor='raw', zero=zero,
  518. add_memory_pressure=add_memory_pressure,
  519. track_allocation=track_allocation)
  520. return _ll_0_raw_malloc_fixedsize
  521. return build_ll_0_raw_malloc_fixedsize
  522. build_ll_0_raw_malloc_fixedsize = (
  523. build_raw_malloc_fixedsize_builder())
  524. build_ll_0_raw_malloc_fixedsize_zero = (
  525. build_raw_malloc_fixedsize_builder(zero=True))
  526. build_ll_0_raw_malloc_fixedsize_zero_add_memory_pressure = (
  527. build_raw_malloc_fixedsize_builder(zero=True, add_memory_pressure=True))
  528. build_ll_0_raw_malloc_fixedsize_add_memory_pressure = (
  529. build_raw_malloc_fixedsize_builder(add_memory_pressure=True))
  530. build_ll_0_raw_malloc_fixedsize_no_track_allocation = (
  531. build_raw_malloc_fixedsize_builder(track_allocation=False))
  532. build_ll_0_raw_malloc_fixedsize_zero_no_track_allocation = (
  533. build_raw_malloc_fixedsize_builder(zero=True, track_allocation=False))
  534. build_ll_0_raw_malloc_fixedsize_zero_add_memory_pressure_no_track_allocation = (
  535. build_raw_malloc_fixedsize_builder(zero=True, add_memory_pressure=True, track_allocation=False))
  536. build_ll_0_raw_malloc_fixedsize_add_memory_pressure_no_track_allocation = (
  537. build_raw_malloc_fixedsize_builder(add_memory_pressure=True, track_allocation=False))
  538. def build_raw_free_builder(track_allocation=True):
  539. def build_ll_1_raw_free(ARRAY):
  540. def _ll_1_raw_free(p):
  541. lltype.free(p, flavor='raw',
  542. track_allocation=track_allocation)
  543. return _ll_1_raw_free
  544. return build_ll_1_raw_free
  545. build_ll_1_raw_free = (
  546. build_raw_free_builder())
  547. build_ll_1_raw_free_no_track_allocation = (
  548. build_raw_free_builder(track_allocation=False))
  549. class OOtypeHelpers:
  550. # ---------- dict ----------
  551. def _ll_0_newdict(DICT):
  552. return oo_rdict.ll_newdict(DICT)
  553. _ll_0_newdict.need_result_type = True
  554. def _ll_3_dict_setitem(d, key, value):
  555. d.ll_set(key, value)
  556. def _ll_2_dict_contains(d, key):
  557. return d.ll_contains(key)
  558. def _ll_1_dict_clear(d):
  559. d.ll_clear()
  560. _ll_2_dict_getitem = oo_rdict.ll_dict_getitem
  561. _ll_2_dict_delitem = oo_rdict.ll_dict_delitem
  562. _ll_3_dict_setdefault = oo_rdict.ll_dict_setdefault
  563. _ll_3_dict_get = oo_rdict.ll_dict_get
  564. _ll_1_dict_copy = oo_rdict.ll_dict_copy
  565. _ll_2_dict_update = oo_rdict.ll_dict_update
  566. # ---------- dict keys(), values(), items(), iter ----------
  567. _ll_1_dict_keys = oo_rdict.ll_dict_keys
  568. _ll_1_dict_values = oo_rdict.ll_dict_values
  569. _ll_1_dict_items = oo_rdict.ll_dict_items
  570. _ll_1_dict_keys .need_result_type = True
  571. _ll_1_dict_values.need_result_type = True
  572. _ll_1_dict_items .need_result_type = True
  573. _dictnext_keys = staticmethod(oo_rdict.ll_dictnext_group['keys'])
  574. _dictnext_values = staticmethod(oo_rdict.ll_dictnext_group['values'])
  575. _dictnext_items = staticmethod(oo_rdict.ll_dictnext_group['items'])
  576. def _ll_1_dictiter_nextkeys(iter):
  577. return OOtypeHelpers._dictnext_keys(None, iter)
  578. def _ll_1_dictiter_nextvalues(iter):
  579. return OOtypeHelpers._dictnext_values(None, iter)
  580. def _ll_1_dictiter_nextitems(RES, iter):
  581. return OOtypeHelpers._dictnext_items(RES, iter)
  582. _ll_1_dictiter_nextitems.need_result_type = True
  583. # --------------- oostring and oounicode ----------------
  584. def _ll_2_oostring_signed_foldable(n, base):
  585. return ootype.oostring(n, base)
  586. def _ll_1_oostring_char_foldable(ch):
  587. return ootype.oostring(ch, -1)
  588. def _ll_1_oostring_unsigned_foldable(n):
  589. return ootype.oostring(n, -1)
  590. def _ll_1_oostring_string_foldable(s):
  591. return ootype.oostring(s, -1)
  592. def _ll_1_oostring_root_foldable(s):
  593. return ootype.oostring(s, -1)
  594. def _ll_2_oounicode_signed_foldable(n, base):
  595. return ootype.oounicode(n, base)
  596. def _ll_1_oounicode_unichar_foldable(ch):
  597. return ootype.oounicode(ch, -1)
  598. def _ll_1_oounicode_string_foldable(s):
  599. return ootype.oounicode(s, -1)
  600. # -------------------------------------------------------
  601. def setup_extra_builtin(rtyper, oopspec_name, nb_args, extra=None):
  602. name = '_ll_%d_%s' % (nb_args, oopspec_name.replace('.', '_'))
  603. if extra is not None:
  604. name = 'build' + name
  605. try:
  606. wrapper = globals()[name]
  607. except KeyError:
  608. if rtyper.type_system.name == 'lltypesystem':
  609. Helpers = LLtypeHelpers
  610. else:
  611. Helpers = OOtypeHelpers
  612. wrapper = getattr(Helpers, name).im_func
  613. if extra is not None:
  614. wrapper = wrapper(*extra)
  615. return wrapper
  616. # # ____________________________________________________________
  617. class Index:
  618. def __init__(self, n):
  619. self.n = n
  620. def parse_oopspec(fnobj):
  621. FUNCTYPE = lltype.typeOf(fnobj)
  622. ll_func = fnobj._callable
  623. nb_args = len(FUNCTYPE.ARGS)
  624. argnames = ll_func.func_code.co_varnames[:nb_args]
  625. # parse the oopspec and fill in the arguments
  626. operation_name, args = ll_func.oopspec.split('(', 1)
  627. assert args.endswith(')')
  628. args = args[:-1] + ',' # trailing comma to force tuple syntax
  629. if args.strip() == ',':
  630. args = '()'
  631. nb_args = len(argnames)
  632. argname2index = dict(zip(argnames, [Index(n) for n in range(nb_args)]))
  633. argtuple = eval(args, argname2index)
  634. return operation_name, argtuple
  635. def normalize_opargs(argtuple, opargs):
  636. result = []
  637. for obj in argtuple:
  638. if isinstance(obj, Index):
  639. result.append(opargs[obj.n])
  640. else:
  641. result.append(Constant(obj, lltype.typeOf(obj)))
  642. return result
  643. def get_call_oopspec_opargs(fnobj, opargs):
  644. oopspec, argtuple = parse_oopspec(fnobj)
  645. normalized_opargs = normalize_opargs(argtuple, opargs)
  646. return oopspec, normalized_opargs
  647. def get_oostring_oopspec(op):
  648. T = op.args[0].concretetype
  649. if T is not ootype.Signed:
  650. args = op.args[:-1]
  651. else:
  652. args = op.args
  653. if isinstance(T, ootype.Instance):
  654. T = ootype.ROOT
  655. return '%s_%s_foldable' % (op.opname, T._name.lower()), args
  656. def get_identityhash_oopspec(op):
  657. return 'gc_identityhash', op.args
  658. def get_gcid_oopspec(op):
  659. return 'gc_id', op.args
  660. RENAMED_ADT_NAME = {
  661. 'list': {
  662. 'll_getitem_fast': 'getitem',
  663. 'll_setitem_fast': 'setitem',
  664. 'll_length': 'len',
  665. },
  666. }
  667. def get_send_oopspec(SELFTYPE, name):
  668. oopspec_name = SELFTYPE.oopspec_name
  669. assert oopspec_name is not None
  670. renamed = RENAMED_ADT_NAME.get(oopspec_name, {})
  671. pubname = renamed.get(name, name)
  672. oopspec = '%s.%s' % (oopspec_name, pubname)
  673. return oopspec
  674. def decode_builtin_call(op):
  675. if op.opname == 'oosend':
  676. SELFTYPE, name, opargs = decompose_oosend(op)
  677. return get_send_oopspec(SELFTYPE, name), opargs
  678. elif op.opname == 'direct_call':
  679. fnobj = get_funcobj(op.args[0].value)
  680. opargs = op.args[1:]
  681. return get_call_oopspec_opargs(fnobj, opargs)
  682. elif op.opname in ('oostring', 'oounicode'):
  683. return get_oostring_oopspec(op)
  684. elif op.opname == 'gc_identityhash':
  685. return get_identityhash_oopspec(op)
  686. elif op.opname == 'gc_id':
  687. return get_gcid_oopspec(op)
  688. else:
  689. raise ValueError(op.opname)
  690. def builtin_func_for_spec(rtyper, oopspec_name, ll_args, ll_res,
  691. extra=None, extrakey=None):
  692. assert (extra is None) == (extrakey is None)
  693. key = (oopspec_name, tuple(ll_args), ll_res, extrakey)
  694. try:
  695. return rtyper._builtin_func_for_spec_cache[key]
  696. except (KeyError, AttributeError):
  697. pass
  698. args_s = [annmodel.lltype_to_annotation(v) for v in ll_args]
  699. if '.' not in oopspec_name: # 'newxxx' operations
  700. LIST_OR_DICT = ll_res
  701. else:
  702. LIST_OR_DICT = ll_args[0]
  703. s_result = annmodel.lltype_to_annotation(ll_res)
  704. impl = setup_extra_builtin(rtyper, oopspec_name, len(args_s), extra)
  705. if getattr(impl, 'need_result_type', False):
  706. bk = rtyper.annotator.bookkeeper
  707. args_s.insert(0, annmodel.SomePBC([bk.getdesc(deref(ll_res))]))
  708. #
  709. if hasattr(rtyper, 'annotator'): # regular case
  710. mixlevelann = MixLevelHelperAnnotator(rtyper)
  711. c_func = mixlevelann.constfunc(impl, args_s, s_result)
  712. mixlevelann.finish()
  713. else:
  714. # for testing only
  715. c_func = Constant(oopspec_name,
  716. lltype.Ptr(lltype.FuncType(ll_args, ll_res)))
  717. #
  718. if not hasattr(rtyper, '_builtin_func_for_spec_cache'):
  719. rtyper._builtin_func_for_spec_cache = {}
  720. rtyper._builtin_func_for_spec_cache[key] = (c_func, LIST_OR_DICT)
  721. #
  722. return c_func, LIST_OR_DICT
  723. def decompose_oosend(op):
  724. name = op.args[0].value
  725. opargs = op.args[1:]
  726. SELFTYPE = opargs[0].concretetype
  727. return SELFTYPE, name, opargs
  728. def lookup_oosend_method(op):
  729. SELFTYPE, methname, args_v = decompose_oosend(op)
  730. _, meth = SELFTYPE._lookup(methname)
  731. return SELFTYPE, methname, meth