PageRenderTime 57ms CodeModel.GetById 26ms RepoModel.GetById 0ms app.codeStats 0ms

/rpython/jit/codewriter/support.py

https://bitbucket.org/pypy/pypy/
Python | 787 lines | 607 code | 130 blank | 50 comment | 63 complexity | 45a5a82fe9e264261e17fd7ddeb8fae2 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. import sys
  2. from rpython.annotator import model as annmodel
  3. from rpython.rtyper.llannotation import lltype_to_annotation
  4. from rpython.annotator.policy import AnnotatorPolicy
  5. from rpython.flowspace.model import Variable, Constant
  6. from rpython.jit.metainterp.typesystem import deref
  7. from rpython.rlib import rgc
  8. from rpython.rlib.jit import elidable, oopspec
  9. from rpython.rlib.rarithmetic import r_longlong, r_ulonglong, r_uint, intmask
  10. from rpython.rlib.rarithmetic import LONG_BIT
  11. from rpython.rtyper import rlist
  12. from rpython.rtyper.lltypesystem import rlist as rlist_ll
  13. from rpython.rtyper.annlowlevel import MixLevelHelperAnnotator
  14. from rpython.rtyper.extregistry import ExtRegistryEntry
  15. from rpython.rtyper.llinterp import LLInterpreter
  16. from rpython.rtyper.lltypesystem import lltype, rffi, llmemory, rstr as ll_rstr, rdict as ll_rdict
  17. from rpython.rtyper import rclass
  18. from rpython.rtyper.lltypesystem import rordereddict
  19. from rpython.rtyper.lltypesystem.lloperation import llop
  20. from rpython.rtyper.lltypesystem.module import ll_math
  21. from rpython.translator.translator import TranslationContext
  22. from rpython.translator.unsimplify import split_block
  23. def getargtypes(annotator, values):
  24. if values is None: # for backend tests producing stand-alone exe's
  25. from rpython.annotator.listdef import s_list_of_strings
  26. return [s_list_of_strings]
  27. return [_annotation(annotator, x) for x in values]
  28. def _annotation(a, x):
  29. T = lltype.typeOf(x)
  30. if T == lltype.Ptr(ll_rstr.STR):
  31. t = str
  32. else:
  33. t = lltype_to_annotation(T)
  34. return a.typeannotation(t)
  35. def annotate(func, values, inline=None, backendoptimize=True,
  36. translationoptions={}):
  37. # build the normal ll graphs for ll_function
  38. t = TranslationContext()
  39. for key, value in translationoptions.items():
  40. setattr(t.config.translation, key, value)
  41. annpolicy = AnnotatorPolicy()
  42. a = t.buildannotator(policy=annpolicy)
  43. argtypes = getargtypes(a, values)
  44. a.build_types(func, argtypes, main_entry_point=True)
  45. rtyper = t.buildrtyper()
  46. rtyper.specialize()
  47. #if inline:
  48. # auto_inlining(t, threshold=inline)
  49. if backendoptimize:
  50. from rpython.translator.backendopt.all import backend_optimizations
  51. backend_optimizations(t, inline_threshold=inline or 0,
  52. remove_asserts=True, really_remove_asserts=True)
  53. return rtyper
  54. def getgraph(func, values):
  55. rtyper = annotate(func, values)
  56. return rtyper.annotator.translator.graphs[0]
  57. def autodetect_jit_markers_redvars(graph):
  58. # the idea is to find all the jit_merge_point and
  59. # add all the variables across the links to the reds.
  60. for block, op in graph.iterblockops():
  61. if op.opname == 'jit_marker':
  62. jitdriver = op.args[1].value
  63. if not jitdriver.autoreds:
  64. continue
  65. # if we want to support also can_enter_jit, we should find a
  66. # way to detect a consistent set of red vars to pass *both* to
  67. # jit_merge_point and can_enter_jit. The current simple
  68. # solution doesn't work because can_enter_jit might be in
  69. # another block, so the set of alive_v will be different.
  70. methname = op.args[0].value
  71. assert methname == 'jit_merge_point', (
  72. "reds='auto' is supported only for jit drivers which "
  73. "calls only jit_merge_point. Found a call to %s" % methname)
  74. #
  75. # compute the set of live variables across the jit_marker
  76. alive_v = set()
  77. for link in block.exits:
  78. alive_v.update(link.args)
  79. alive_v.difference_update(link.getextravars())
  80. for op1 in block.operations[::-1]:
  81. if op1 is op:
  82. break # stop when the meet the jit_marker
  83. alive_v.discard(op1.result)
  84. alive_v.update(op1.args)
  85. greens_v = op.args[2:]
  86. reds_v = alive_v - set(greens_v)
  87. reds_v = [v for v in reds_v if isinstance(v, Variable) and
  88. v.concretetype is not lltype.Void]
  89. reds_v = sort_vars(reds_v)
  90. op.args.extend(reds_v)
  91. if jitdriver.numreds is None:
  92. jitdriver.numreds = len(reds_v)
  93. elif jitdriver.numreds != len(reds_v):
  94. raise AssertionError("there are multiple jit_merge_points "
  95. "with the same jitdriver")
  96. def split_before_jit_merge_point(graph, portalblock, portalopindex):
  97. """Split the block just before the 'jit_merge_point',
  98. making sure the input args are in the canonical order.
  99. """
  100. # split the block just before the jit_merge_point()
  101. if portalopindex > 0:
  102. link = split_block(portalblock, portalopindex)
  103. portalblock = link.target
  104. portalop = portalblock.operations[0]
  105. # split again, this time enforcing the order of the live vars
  106. # specified by decode_hp_hint_args().
  107. assert portalop.opname == 'jit_marker'
  108. assert portalop.args[0].value == 'jit_merge_point'
  109. greens_v, reds_v = decode_hp_hint_args(portalop)
  110. link = split_block(portalblock, 0, greens_v + reds_v)
  111. return link.target
  112. def sort_vars(args_v):
  113. from rpython.jit.metainterp.history import getkind
  114. _kind2count = {'int': 1, 'ref': 2, 'float': 3}
  115. return sorted(args_v, key=lambda v: _kind2count[getkind(v.concretetype)])
  116. def decode_hp_hint_args(op):
  117. # Returns (list-of-green-vars, list-of-red-vars) without Voids.
  118. # Both lists must be sorted: first INT, then REF, then FLOAT.
  119. assert op.opname == 'jit_marker'
  120. jitdriver = op.args[1].value
  121. numgreens = len(jitdriver.greens)
  122. assert jitdriver.numreds is not None
  123. numreds = jitdriver.numreds
  124. greens_v = op.args[2:2+numgreens]
  125. reds_v = op.args[2+numgreens:]
  126. assert len(reds_v) == numreds
  127. #
  128. def _sort(args_v, is_green):
  129. lst = [v for v in args_v if v.concretetype is not lltype.Void]
  130. if is_green:
  131. assert len(lst) == len(args_v), (
  132. "not supported so far: 'greens' variables contain Void")
  133. # a crash here means that you have to reorder the variable named in
  134. # the JitDriver. Indeed, greens and reds must both be sorted: first
  135. # all INTs, followed by all REFs, followed by all FLOATs.
  136. lst2 = sort_vars(lst)
  137. assert lst == lst2
  138. return lst
  139. #
  140. return (_sort(greens_v, True), _sort(reds_v, False))
  141. def maybe_on_top_of_llinterp(rtyper, fnptr):
  142. # Run a generated graph on top of the llinterp for testing.
  143. # When translated, this just returns the fnptr.
  144. funcobj = fnptr._obj
  145. if hasattr(funcobj, 'graph'):
  146. llinterp = LLInterpreter(rtyper) #, exc_data_ptr=exc_data_ptr)
  147. def on_top_of_llinterp(*args):
  148. return llinterp.eval_graph(funcobj.graph, list(args))
  149. else:
  150. assert hasattr(funcobj, '_callable')
  151. def on_top_of_llinterp(*args):
  152. return funcobj._callable(*args)
  153. return on_top_of_llinterp
  154. class Entry(ExtRegistryEntry):
  155. _about_ = maybe_on_top_of_llinterp
  156. def compute_result_annotation(self, s_rtyper, s_fnptr):
  157. return s_fnptr
  158. def specialize_call(self, hop):
  159. hop.exception_cannot_occur()
  160. return hop.inputarg(hop.args_r[1], arg=1)
  161. # ____________________________________________________________
  162. #
  163. # Manually map oopspec'ed operations back to their ll implementation
  164. # coming from modules like rpython.rtyper.rlist. The following
  165. # functions are fished from the globals() by setup_extra_builtin().
  166. def _ll_0_newlist(LIST):
  167. return LIST.ll_newlist(0)
  168. def _ll_1_newlist(LIST, count):
  169. return LIST.ll_newlist(count)
  170. _ll_0_newlist.need_result_type = True
  171. _ll_1_newlist.need_result_type = True
  172. _ll_1_newlist_clear = rlist._ll_alloc_and_clear
  173. _ll_1_newlist_clear.need_result_type = True
  174. def _ll_1_newlist_hint(LIST, hint):
  175. return LIST.ll_newlist_hint(hint)
  176. _ll_1_newlist_hint.need_result_type = True
  177. def _ll_1_list_len(l):
  178. return l.ll_length()
  179. def _ll_2_list_getitem(l, index):
  180. return rlist.ll_getitem(rlist.dum_checkidx, l, index)
  181. def _ll_3_list_setitem(l, index, newitem):
  182. rlist.ll_setitem(rlist.dum_checkidx, l, index, newitem)
  183. def _ll_2_list_delitem(l, index):
  184. rlist.ll_delitem(rlist.dum_checkidx, l, index)
  185. def _ll_1_list_pop(l):
  186. return rlist.ll_pop_default(rlist.dum_checkidx, l)
  187. def _ll_2_list_pop(l, index):
  188. return rlist.ll_pop(rlist.dum_checkidx, l, index)
  189. _ll_2_list_append = rlist.ll_append
  190. _ll_2_list_extend = rlist.ll_extend
  191. _ll_3_list_insert = rlist.ll_insert_nonneg
  192. _ll_2_list_delslice_startonly = rlist.ll_listdelslice_startonly
  193. _ll_3_list_delslice_startstop = rlist.ll_listdelslice_startstop
  194. _ll_2_list_inplace_mul = rlist.ll_inplace_mul
  195. _ll_2_list_getitem_foldable = _ll_2_list_getitem
  196. _ll_1_list_len_foldable = _ll_1_list_len
  197. _ll_5_list_ll_arraycopy = rgc.ll_arraycopy
  198. _ll_3_list_resize_hint_really = rlist_ll._ll_list_resize_hint_really
  199. @elidable
  200. def _ll_1_gc_identityhash(x):
  201. return lltype.identityhash(x)
  202. # the following function should not be "@elidable": I can think of
  203. # a corner case in which id(const) is constant-folded, and then 'const'
  204. # disappears and is collected too early (possibly causing another object
  205. # with the same id() to appear).
  206. def _ll_1_gc_id(ptr):
  207. return llop.gc_id(lltype.Signed, ptr)
  208. def _ll_1_gc_pin(ptr):
  209. return llop.gc_pin(lltype.Bool, ptr)
  210. def _ll_1_gc_unpin(ptr):
  211. llop.gc_unpin(lltype.Void, ptr)
  212. @oopspec("jit.force_virtual(inst)")
  213. def _ll_1_jit_force_virtual(inst):
  214. return llop.jit_force_virtual(lltype.typeOf(inst), inst)
  215. def _ll_1_int_abs(x):
  216. # this version doesn't branch
  217. mask = x >> (LONG_BIT - 1)
  218. return (x ^ mask) - mask
  219. def _ll_2_int_floordiv(x, y):
  220. # this is used only if the RPython program uses llop.int_floordiv()
  221. # explicitly. For 'a // b', see _handle_int_special() in jtransform.py.
  222. # This is the reverse of rpython.rtyper.rint.ll_int_py_div(), i.e.
  223. # the same logic as rpython.rtyper.lltypesystem.opimpl.op_int_floordiv
  224. # but written in a no-branch style.
  225. r = x // y
  226. p = r * y
  227. # the JIT knows that if x and y are both positive, this is just 'r'
  228. return r + (((x ^ y) >> (LONG_BIT - 1)) & (p != x))
  229. def _ll_2_int_mod(x, y):
  230. # same comments as _ll_2_int_floordiv()
  231. r = x % y
  232. # the JIT knows that if x and y are both positive, this doesn't change 'r'
  233. r -= y & (((x ^ y) & (r | -r)) >> (LONG_BIT - 1))
  234. return r
  235. def _ll_1_cast_uint_to_float(x):
  236. # XXX on 32-bit platforms, this should be done using cast_longlong_to_float
  237. # (which is a residual call right now in the x86 backend)
  238. return llop.cast_uint_to_float(lltype.Float, x)
  239. def _ll_1_cast_float_to_uint(x):
  240. # XXX on 32-bit platforms, this should be done using cast_float_to_longlong
  241. # (which is a residual call right now in the x86 backend)
  242. return llop.cast_float_to_uint(lltype.Unsigned, x)
  243. def _ll_0_ll_read_timestamp():
  244. from rpython.rlib import rtimer
  245. return rtimer.read_timestamp()
  246. # math support
  247. # ------------
  248. _ll_1_ll_math_ll_math_sqrt = ll_math.ll_math_sqrt
  249. # long long support
  250. # -----------------
  251. def u_to_longlong(x):
  252. return rffi.cast(lltype.SignedLongLong, x)
  253. def _ll_1_llong_invert(xll):
  254. y = ~r_ulonglong(xll)
  255. return u_to_longlong(y)
  256. def _ll_1_ullong_invert(xull):
  257. return ~xull
  258. def _ll_2_llong_lt(xll, yll):
  259. return xll < yll
  260. def _ll_2_llong_le(xll, yll):
  261. return xll <= yll
  262. def _ll_2_llong_eq(xll, yll):
  263. return xll == yll
  264. def _ll_2_llong_ne(xll, yll):
  265. return xll != yll
  266. def _ll_2_llong_gt(xll, yll):
  267. return xll > yll
  268. def _ll_2_llong_ge(xll, yll):
  269. return xll >= yll
  270. def _ll_2_ullong_eq(xull, yull):
  271. return xull == yull
  272. def _ll_2_ullong_ne(xull, yull):
  273. return xull != yull
  274. def _ll_2_ullong_ult(xull, yull):
  275. return xull < yull
  276. def _ll_2_ullong_ule(xull, yull):
  277. return xull <= yull
  278. def _ll_2_ullong_ugt(xull, yull):
  279. return xull > yull
  280. def _ll_2_ullong_uge(xull, yull):
  281. return xull >= yull
  282. def _ll_2_llong_add(xll, yll):
  283. z = r_ulonglong(xll) + r_ulonglong(yll)
  284. return u_to_longlong(z)
  285. def _ll_2_llong_sub(xll, yll):
  286. z = r_ulonglong(xll) - r_ulonglong(yll)
  287. return u_to_longlong(z)
  288. def _ll_2_llong_mul(xll, yll):
  289. z = r_ulonglong(xll) * r_ulonglong(yll)
  290. return u_to_longlong(z)
  291. def _ll_2_llong_and(xll, yll):
  292. z = r_ulonglong(xll) & r_ulonglong(yll)
  293. return u_to_longlong(z)
  294. def _ll_2_llong_or(xll, yll):
  295. z = r_ulonglong(xll) | r_ulonglong(yll)
  296. return u_to_longlong(z)
  297. def _ll_2_llong_xor(xll, yll):
  298. z = r_ulonglong(xll) ^ r_ulonglong(yll)
  299. return u_to_longlong(z)
  300. def _ll_2_ullong_add(xull, yull):
  301. z = (xull) + (yull)
  302. return (z)
  303. def _ll_2_ullong_sub(xull, yull):
  304. z = (xull) - (yull)
  305. return (z)
  306. def _ll_2_ullong_mul(xull, yull):
  307. z = (xull) * (yull)
  308. return (z)
  309. def _ll_2_ullong_and(xull, yull):
  310. z = (xull) & (yull)
  311. return (z)
  312. def _ll_2_ullong_or(xull, yull):
  313. z = (xull) | (yull)
  314. return (z)
  315. def _ll_2_ullong_xor(xull, yull):
  316. z = (xull) ^ (yull)
  317. return (z)
  318. def _ll_2_llong_lshift(xll, y):
  319. z = r_ulonglong(xll) << y
  320. return u_to_longlong(z)
  321. def _ll_2_ullong_lshift(xull, y):
  322. return xull << y
  323. def _ll_2_llong_rshift(xll, y):
  324. return xll >> y
  325. def _ll_2_ullong_urshift(xull, y):
  326. return xull >> y
  327. def _ll_1_llong_from_int(x):
  328. return r_longlong(intmask(x))
  329. def _ll_1_ullong_from_int(x):
  330. return r_ulonglong(intmask(x))
  331. def _ll_1_llong_from_uint(x):
  332. return r_longlong(r_uint(x))
  333. def _ll_1_ullong_from_uint(x):
  334. return r_ulonglong(r_uint(x))
  335. def _ll_1_llong_to_int(xll):
  336. return intmask(xll)
  337. def _ll_1_llong_from_float(xf):
  338. return r_longlong(xf)
  339. def _ll_1_ullong_from_float(xf):
  340. return r_ulonglong(xf)
  341. def _ll_1_llong_to_float(xll):
  342. return float(rffi.cast(lltype.SignedLongLong, xll))
  343. def _ll_1_ullong_u_to_float(xull):
  344. return float(rffi.cast(lltype.UnsignedLongLong, xull))
  345. def _ll_1_llong_abs(xll):
  346. if xll < 0:
  347. return -xll
  348. else:
  349. return xll
  350. # in the following calls to builtins, the JIT is allowed to look inside:
  351. inline_calls_to = [
  352. ('int_abs', [lltype.Signed], lltype.Signed),
  353. ('int_floordiv', [lltype.Signed, lltype.Signed], lltype.Signed),
  354. ('int_mod', [lltype.Signed, lltype.Signed], lltype.Signed),
  355. ('ll_math.ll_math_sqrt', [lltype.Float], lltype.Float),
  356. ]
  357. class LLtypeHelpers:
  358. # ---------- dict ----------
  359. _ll_1_dict_copy = ll_rdict.ll_copy
  360. _ll_1_dict_clear = ll_rdict.ll_clear
  361. _ll_2_dict_update = ll_rdict.ll_update
  362. # ---------- dict keys(), values(), items(), iter ----------
  363. _ll_1_dict_keys = ll_rdict.ll_dict_keys
  364. _ll_1_dict_values = ll_rdict.ll_dict_values
  365. _ll_1_dict_items = ll_rdict.ll_dict_items
  366. _ll_1_dict_keys .need_result_type = True
  367. _ll_1_dict_values.need_result_type = True
  368. _ll_1_dict_items .need_result_type = True
  369. _ll_1_dictiter_next = ll_rdict._ll_dictnext
  370. _ll_1_dict_resize = ll_rdict.ll_dict_resize
  371. # ---------- ordered dict ----------
  372. _ll_1_odict_copy = rordereddict.ll_dict_copy
  373. _ll_1_odict_clear = rordereddict.ll_dict_clear
  374. _ll_2_odict_update = rordereddict.ll_dict_update
  375. _ll_1_odict_keys = rordereddict.ll_dict_keys
  376. _ll_1_odict_values = rordereddict.ll_dict_values
  377. _ll_1_odict_items = rordereddict.ll_dict_items
  378. _ll_1_odict_keys .need_result_type = True
  379. _ll_1_odict_values.need_result_type = True
  380. _ll_1_odict_items .need_result_type = True
  381. _ll_1_odictiter_next = rordereddict._ll_dictnext
  382. _ll_1_odict_resize = rordereddict.ll_dict_resize
  383. # ---------- strings and unicode ----------
  384. _ll_1_str_str2unicode = ll_rstr.LLHelpers.ll_str2unicode
  385. def _ll_4_str_eq_slice_checknull(s1, start, length, s2):
  386. """str1[start : start + length] == str2."""
  387. if not s2:
  388. return 0
  389. chars2 = s2.chars
  390. if len(chars2) != length:
  391. return 0
  392. j = 0
  393. chars1 = s1.chars
  394. while j < length:
  395. if chars1[start + j] != chars2[j]:
  396. return 0
  397. j += 1
  398. return 1
  399. def _ll_4_str_eq_slice_nonnull(s1, start, length, s2):
  400. """str1[start : start + length] == str2, assuming str2 != NULL."""
  401. chars2 = s2.chars
  402. if len(chars2) != length:
  403. return 0
  404. j = 0
  405. chars1 = s1.chars
  406. while j < length:
  407. if chars1[start + j] != chars2[j]:
  408. return 0
  409. j += 1
  410. return 1
  411. def _ll_4_str_eq_slice_char(s1, start, length, c2):
  412. """str1[start : start + length] == c2."""
  413. if length != 1:
  414. return 0
  415. if s1.chars[start] != c2:
  416. return 0
  417. return 1
  418. def _ll_2_str_eq_nonnull(s1, s2):
  419. len1 = len(s1.chars)
  420. len2 = len(s2.chars)
  421. if len1 != len2:
  422. return 0
  423. j = 0
  424. chars1 = s1.chars
  425. chars2 = s2.chars
  426. while j < len1:
  427. if chars1[j] != chars2[j]:
  428. return 0
  429. j += 1
  430. return 1
  431. def _ll_2_str_eq_nonnull_char(s1, c2):
  432. chars = s1.chars
  433. if len(chars) != 1:
  434. return 0
  435. if chars[0] != c2:
  436. return 0
  437. return 1
  438. def _ll_2_str_eq_checknull_char(s1, c2):
  439. if not s1:
  440. return 0
  441. chars = s1.chars
  442. if len(chars) != 1:
  443. return 0
  444. if chars[0] != c2:
  445. return 0
  446. return 1
  447. def _ll_2_str_eq_lengthok(s1, s2):
  448. j = 0
  449. chars1 = s1.chars
  450. chars2 = s2.chars
  451. len1 = len(chars1)
  452. while j < len1:
  453. if chars1[j] != chars2[j]:
  454. return 0
  455. j += 1
  456. return 1
  457. # ---------- malloc with del ----------
  458. def _ll_2_raw_malloc(TP, size):
  459. return lltype.malloc(TP, size, flavor='raw')
  460. def build_ll_0_alloc_with_del(RESULT, vtable):
  461. def _ll_0_alloc_with_del():
  462. p = lltype.malloc(RESULT.TO)
  463. lltype.cast_pointer(rclass.OBJECTPTR, p).typeptr = vtable
  464. return p
  465. return _ll_0_alloc_with_del
  466. def build_raw_malloc_varsize_builder(zero=False,
  467. add_memory_pressure=False,
  468. track_allocation=True):
  469. def build_ll_1_raw_malloc_varsize(ARRAY):
  470. def _ll_1_raw_malloc_varsize(n):
  471. return lltype.malloc(ARRAY, n, flavor='raw', zero=zero,
  472. add_memory_pressure=add_memory_pressure,
  473. track_allocation=track_allocation)
  474. return _ll_1_raw_malloc_varsize
  475. return build_ll_1_raw_malloc_varsize
  476. build_ll_1_raw_malloc_varsize = (
  477. build_raw_malloc_varsize_builder())
  478. build_ll_1_raw_malloc_varsize_zero = (
  479. build_raw_malloc_varsize_builder(zero=True))
  480. build_ll_1_raw_malloc_varsize_zero_add_memory_pressure = (
  481. build_raw_malloc_varsize_builder(zero=True, add_memory_pressure=True))
  482. build_ll_1_raw_malloc_varsize_add_memory_pressure = (
  483. build_raw_malloc_varsize_builder(add_memory_pressure=True))
  484. build_ll_1_raw_malloc_varsize_no_track_allocation = (
  485. build_raw_malloc_varsize_builder(track_allocation=False))
  486. build_ll_1_raw_malloc_varsize_zero_no_track_allocation = (
  487. build_raw_malloc_varsize_builder(zero=True, track_allocation=False))
  488. build_ll_1_raw_malloc_varsize_zero_add_memory_pressure_no_track_allocation = (
  489. build_raw_malloc_varsize_builder(zero=True, add_memory_pressure=True, track_allocation=False))
  490. build_ll_1_raw_malloc_varsize_add_memory_pressure_no_track_allocation = (
  491. build_raw_malloc_varsize_builder(add_memory_pressure=True, track_allocation=False))
  492. def build_raw_malloc_fixedsize_builder(zero=False,
  493. add_memory_pressure=False,
  494. track_allocation=True):
  495. def build_ll_0_raw_malloc_fixedsize(STRUCT):
  496. def _ll_0_raw_malloc_fixedsize():
  497. return lltype.malloc(STRUCT, flavor='raw', zero=zero,
  498. add_memory_pressure=add_memory_pressure,
  499. track_allocation=track_allocation)
  500. return _ll_0_raw_malloc_fixedsize
  501. return build_ll_0_raw_malloc_fixedsize
  502. build_ll_0_raw_malloc_fixedsize = (
  503. build_raw_malloc_fixedsize_builder())
  504. build_ll_0_raw_malloc_fixedsize_zero = (
  505. build_raw_malloc_fixedsize_builder(zero=True))
  506. build_ll_0_raw_malloc_fixedsize_zero_add_memory_pressure = (
  507. build_raw_malloc_fixedsize_builder(zero=True, add_memory_pressure=True))
  508. build_ll_0_raw_malloc_fixedsize_add_memory_pressure = (
  509. build_raw_malloc_fixedsize_builder(add_memory_pressure=True))
  510. build_ll_0_raw_malloc_fixedsize_no_track_allocation = (
  511. build_raw_malloc_fixedsize_builder(track_allocation=False))
  512. build_ll_0_raw_malloc_fixedsize_zero_no_track_allocation = (
  513. build_raw_malloc_fixedsize_builder(zero=True, track_allocation=False))
  514. build_ll_0_raw_malloc_fixedsize_zero_add_memory_pressure_no_track_allocation = (
  515. build_raw_malloc_fixedsize_builder(zero=True, add_memory_pressure=True, track_allocation=False))
  516. build_ll_0_raw_malloc_fixedsize_add_memory_pressure_no_track_allocation = (
  517. build_raw_malloc_fixedsize_builder(add_memory_pressure=True, track_allocation=False))
  518. def build_raw_free_builder(track_allocation=True):
  519. def build_ll_1_raw_free(ARRAY):
  520. def _ll_1_raw_free(p):
  521. lltype.free(p, flavor='raw',
  522. track_allocation=track_allocation)
  523. return _ll_1_raw_free
  524. return build_ll_1_raw_free
  525. build_ll_1_raw_free = (
  526. build_raw_free_builder())
  527. build_ll_1_raw_free_no_track_allocation = (
  528. build_raw_free_builder(track_allocation=False))
  529. def _ll_1_threadlocalref_get(TP, offset):
  530. return llop.threadlocalref_get(TP, offset)
  531. _ll_1_threadlocalref_get.need_result_type = 'exact' # don't deref
  532. def _ll_1_weakref_create(obj):
  533. return llop.weakref_create(llmemory.WeakRefPtr, obj)
  534. def _ll_1_weakref_deref(TP, obj):
  535. return llop.weakref_deref(lltype.Ptr(TP), obj)
  536. _ll_1_weakref_deref.need_result_type = True
  537. def _ll_1_gc_add_memory_pressure(num):
  538. llop.gc_add_memory_pressure(lltype.Void, num)
  539. def setup_extra_builtin(rtyper, oopspec_name, nb_args, extra=None):
  540. name = '_ll_%d_%s' % (nb_args, oopspec_name.replace('.', '_'))
  541. if extra is not None:
  542. name = 'build' + name
  543. try:
  544. wrapper = globals()[name]
  545. except KeyError:
  546. wrapper = getattr(LLtypeHelpers, name).im_func
  547. if extra is not None:
  548. wrapper = wrapper(*extra)
  549. return wrapper
  550. # # ____________________________________________________________
  551. class Index:
  552. def __init__(self, n):
  553. self.n = n
  554. def parse_oopspec(fnobj):
  555. FUNCTYPE = lltype.typeOf(fnobj)
  556. ll_func = fnobj._callable
  557. nb_args = len(FUNCTYPE.ARGS)
  558. argnames = ll_func.func_code.co_varnames[:nb_args]
  559. # parse the oopspec and fill in the arguments
  560. operation_name, args = ll_func.oopspec.split('(', 1)
  561. assert args.endswith(')')
  562. args = args[:-1] + ',' # trailing comma to force tuple syntax
  563. if args.strip() == ',':
  564. args = '()'
  565. nb_args = len(argnames)
  566. argname2index = dict(zip(argnames, [Index(n) for n in range(nb_args)]))
  567. argtuple = eval(args, argname2index)
  568. return operation_name, argtuple
  569. def normalize_opargs(argtuple, opargs):
  570. result = []
  571. for obj in argtuple:
  572. if isinstance(obj, Index):
  573. result.append(opargs[obj.n])
  574. else:
  575. result.append(Constant(obj, lltype.typeOf(obj)))
  576. return result
  577. def get_call_oopspec_opargs(fnobj, opargs):
  578. oopspec, argtuple = parse_oopspec(fnobj)
  579. normalized_opargs = normalize_opargs(argtuple, opargs)
  580. return oopspec, normalized_opargs
  581. def get_identityhash_oopspec(op):
  582. return 'gc_identityhash', op.args
  583. def get_gcid_oopspec(op):
  584. return 'gc_id', op.args
  585. RENAMED_ADT_NAME = {
  586. 'list': {
  587. 'll_getitem_fast': 'getitem',
  588. 'll_setitem_fast': 'setitem',
  589. 'll_length': 'len',
  590. },
  591. }
  592. def get_send_oopspec(SELFTYPE, name):
  593. oopspec_name = SELFTYPE.oopspec_name
  594. assert oopspec_name is not None
  595. renamed = RENAMED_ADT_NAME.get(oopspec_name, {})
  596. pubname = renamed.get(name, name)
  597. oopspec = '%s.%s' % (oopspec_name, pubname)
  598. return oopspec
  599. def decode_builtin_call(op):
  600. if op.opname == 'direct_call':
  601. fnobj = op.args[0].value._obj
  602. opargs = op.args[1:]
  603. return get_call_oopspec_opargs(fnobj, opargs)
  604. elif op.opname == 'gc_identityhash':
  605. return get_identityhash_oopspec(op)
  606. elif op.opname == 'gc_id':
  607. return get_gcid_oopspec(op)
  608. else:
  609. raise ValueError(op.opname)
  610. def builtin_func_for_spec(rtyper, oopspec_name, ll_args, ll_res,
  611. extra=None, extrakey=None):
  612. assert (extra is None) == (extrakey is None)
  613. key = (oopspec_name, tuple(ll_args), ll_res, extrakey)
  614. try:
  615. return rtyper._builtin_func_for_spec_cache[key]
  616. except (KeyError, AttributeError):
  617. pass
  618. args_s = [lltype_to_annotation(v) for v in ll_args]
  619. if '.' not in oopspec_name: # 'newxxx' operations
  620. LIST_OR_DICT = ll_res
  621. else:
  622. LIST_OR_DICT = ll_args[0]
  623. s_result = lltype_to_annotation(ll_res)
  624. impl = setup_extra_builtin(rtyper, oopspec_name, len(args_s), extra)
  625. if getattr(impl, 'need_result_type', False):
  626. if hasattr(rtyper, 'annotator'):
  627. bk = rtyper.annotator.bookkeeper
  628. ll_restype = ll_res
  629. if impl.need_result_type != 'exact':
  630. ll_restype = deref(ll_restype)
  631. desc = bk.getdesc(ll_restype)
  632. else:
  633. class TestingDesc(object):
  634. knowntype = int
  635. pyobj = None
  636. desc = TestingDesc()
  637. args_s.insert(0, annmodel.SomePBC([desc]))
  638. #
  639. if hasattr(rtyper, 'annotator'): # regular case
  640. mixlevelann = MixLevelHelperAnnotator(rtyper)
  641. c_func = mixlevelann.constfunc(impl, args_s, s_result)
  642. mixlevelann.finish()
  643. else:
  644. # for testing only
  645. c_func = Constant(oopspec_name,
  646. lltype.Ptr(lltype.FuncType(ll_args, ll_res)))
  647. #
  648. if not hasattr(rtyper, '_builtin_func_for_spec_cache'):
  649. rtyper._builtin_func_for_spec_cache = {}
  650. rtyper._builtin_func_for_spec_cache[key] = (c_func, LIST_OR_DICT)
  651. #
  652. return c_func, LIST_OR_DICT