PageRenderTime 48ms CodeModel.GetById 12ms RepoModel.GetById 1ms app.codeStats 0ms

/rpython/jit/backend/llsupport/test/zrpy_gc_test.py

https://bitbucket.org/pypy/pypy/
Python | 905 lines | 785 code | 68 blank | 52 comment | 33 complexity | 510b606cd279a64be57d76aaa0e70f09 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. """
  2. This is a test that translates a complete JIT together with a GC and runs it.
  3. It is testing that the GC-dependent aspects basically work, mostly the mallocs
  4. and the various cases of write barrier.
  5. """
  6. import weakref
  7. import os, py
  8. from rpython.rlib import rgc
  9. from rpython.rtyper.lltypesystem import lltype
  10. from rpython.rlib.jit import JitDriver, dont_look_inside
  11. from rpython.rlib.jit import elidable, unroll_safe
  12. from rpython.rlib.jit import promote
  13. from rpython.jit.backend.llsupport.gc import GcLLDescr_framework
  14. from rpython.tool.udir import udir
  15. from rpython.config.translationoption import DEFL_GC
  16. from rpython.config.config import ConfigError
  17. class X(object):
  18. def __init__(self, x=0):
  19. self.x = x
  20. next = None
  21. class Y(object):
  22. # for pinning tests we need an object without references to other
  23. # objects
  24. def __init__(self, x=0):
  25. self.x = x
  26. class CheckError(Exception):
  27. pass
  28. def check(flag):
  29. if not flag:
  30. raise CheckError
  31. def get_entry(g):
  32. def entrypoint(args):
  33. name = ''
  34. n = 2000
  35. argc = len(args)
  36. if argc > 1:
  37. name = args[1]
  38. if argc > 2:
  39. n = int(args[2])
  40. r_list = []
  41. for i in range(20):
  42. r = g(name, n)
  43. r_list.append(r)
  44. rgc.collect()
  45. rgc.collect(); rgc.collect()
  46. freed = 0
  47. for r in r_list:
  48. if r() is None:
  49. freed += 1
  50. print freed
  51. return 0
  52. return entrypoint
  53. def get_functions_to_patch():
  54. from rpython.jit.backend.llsupport import gc
  55. #
  56. can_use_nursery_malloc1 = gc.GcLLDescr_framework.can_use_nursery_malloc
  57. def can_use_nursery_malloc2(*args):
  58. try:
  59. if os.environ['PYPY_NO_INLINE_MALLOC']:
  60. return False
  61. except KeyError:
  62. pass
  63. return can_use_nursery_malloc1(*args)
  64. #
  65. return {(gc.GcLLDescr_framework, 'can_use_nursery_malloc'):
  66. can_use_nursery_malloc2}
  67. def compile(f, gc, **kwds):
  68. from rpython.annotator.listdef import s_list_of_strings
  69. from rpython.translator.translator import TranslationContext
  70. from rpython.jit.metainterp.warmspot import apply_jit
  71. from rpython.translator.c import genc
  72. #
  73. t = TranslationContext()
  74. t.config.translation.gc = gc
  75. if gc != 'boehm':
  76. t.config.translation.gcremovetypeptr = True
  77. for name, value in kwds.items():
  78. setattr(t.config.translation, name, value)
  79. ann = t.buildannotator()
  80. ann.build_types(f, [s_list_of_strings], main_entry_point=True)
  81. t.buildrtyper().specialize()
  82. if kwds['jit']:
  83. patch = get_functions_to_patch()
  84. old_value = {}
  85. try:
  86. for (obj, attr), value in patch.items():
  87. old_value[obj, attr] = getattr(obj, attr)
  88. setattr(obj, attr, value)
  89. #
  90. apply_jit(t)
  91. #
  92. finally:
  93. for (obj, attr), oldvalue in old_value.items():
  94. setattr(obj, attr, oldvalue)
  95. cbuilder = genc.CStandaloneBuilder(t, f, t.config)
  96. cbuilder.generate_source(defines=cbuilder.DEBUG_DEFINES)
  97. cbuilder.compile()
  98. return cbuilder
  99. def run(cbuilder, args=''):
  100. #
  101. pypylog = udir.join('test_zrpy_gc.log')
  102. env = os.environ.copy()
  103. env['PYPYLOG'] = ':%s' % pypylog
  104. data = cbuilder.cmdexec(args, env=env)
  105. return data.strip()
  106. # ______________________________________________________________________
  107. class BaseFrameworkTests(object):
  108. gc = DEFL_GC
  109. def setup_class(cls):
  110. funcs = []
  111. name_to_func = {}
  112. for fullname in dir(cls):
  113. if not fullname.startswith('define'):
  114. continue
  115. definefunc = getattr(cls, fullname)
  116. _, name = fullname.split('_', 1)
  117. beforefunc, loopfunc, afterfunc = definefunc.im_func(cls)
  118. if beforefunc is None:
  119. def beforefunc(n, x):
  120. return n, x, None, None, None, None, None, None, None, None, None, ''
  121. if afterfunc is None:
  122. def afterfunc(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s):
  123. pass
  124. beforefunc.func_name = 'before_'+name
  125. loopfunc.func_name = 'loop_'+name
  126. afterfunc.func_name = 'after_'+name
  127. funcs.append((beforefunc, loopfunc, afterfunc))
  128. assert name not in name_to_func
  129. name_to_func[name] = len(name_to_func)
  130. print name_to_func
  131. def allfuncs(name, n):
  132. x = X()
  133. x.foo = 2
  134. main_allfuncs(name, n, x)
  135. x.foo = 5
  136. return weakref.ref(x)
  137. def main_allfuncs(name, n, x):
  138. num = name_to_func[name]
  139. n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s = funcs[num][0](n, x)
  140. while n > 0:
  141. myjitdriver.can_enter_jit(num=num, n=n, x=x, x0=x0, x1=x1,
  142. x2=x2, x3=x3, x4=x4, x5=x5, x6=x6, x7=x7, l=l, s=s)
  143. myjitdriver.jit_merge_point(num=num, n=n, x=x, x0=x0, x1=x1,
  144. x2=x2, x3=x3, x4=x4, x5=x5, x6=x6, x7=x7, l=l, s=s)
  145. n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s = funcs[num][1](
  146. n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s)
  147. funcs[num][2](n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s)
  148. myjitdriver = JitDriver(greens = ['num'],
  149. reds = ['n', 'x', 'x0', 'x1', 'x2', 'x3', 'x4',
  150. 'x5', 'x6', 'x7', 'l', 's'], is_recursive=True)
  151. cls.main_allfuncs = staticmethod(main_allfuncs)
  152. cls.name_to_func = name_to_func
  153. OLD_DEBUG = GcLLDescr_framework.DEBUG
  154. try:
  155. GcLLDescr_framework.DEBUG = True
  156. cls.cbuilder = compile(get_entry(allfuncs), cls.gc,
  157. gcrootfinder=cls.gcrootfinder, jit=True,
  158. thread=True)
  159. except ConfigError as e:
  160. assert str(e).startswith('invalid value asmgcc')
  161. py.test.skip('asmgcc not supported')
  162. finally:
  163. GcLLDescr_framework.DEBUG = OLD_DEBUG
  164. def _run(self, name, n, env):
  165. res = self.cbuilder.cmdexec("%s %d" %(name, n), env=env)
  166. assert int(res) == 20
  167. def run(self, name, n=2000):
  168. pypylog = udir.join('TestCompileFramework.log')
  169. env = os.environ.copy()
  170. env['PYPYLOG'] = ':%s' % pypylog
  171. env['PYPY_NO_INLINE_MALLOC'] = '1'
  172. self._run(name, n, env)
  173. env['PYPY_NO_INLINE_MALLOC'] = ''
  174. self._run(name, n, env)
  175. def run_orig(self, name, n, x):
  176. self.main_allfuncs(name, n, x)
  177. class CompileFrameworkTests(BaseFrameworkTests):
  178. # Test suite using (so far) the minimark GC.
  179. ## def define_libffi_workaround(cls):
  180. ## # XXX: this is a workaround for a bug in database.py. It seems that
  181. ## # the problem is triggered by optimizeopt/fficall.py, and in
  182. ## # particular by the ``cast_base_ptr_to_instance(Func, llfunc)``: in
  183. ## # these tests, that line is the only place where libffi.Func is
  184. ## # referenced.
  185. ## #
  186. ## # The problem occurs because the gctransformer tries to annotate a
  187. ## # low-level helper to call the __del__ of libffi.Func when it's too
  188. ## # late.
  189. ## #
  190. ## # This workaround works by forcing the annotator (and all the rest of
  191. ## # the toolchain) to see libffi.Func in a "proper" context, not just as
  192. ## # the target of cast_base_ptr_to_instance. Note that the function
  193. ## # below is *never* called by any actual test, it's just annotated.
  194. ## #
  195. ## from rpython.rlib.libffi import get_libc_name, CDLL, types, ArgChain
  196. ## libc_name = get_libc_name()
  197. ## def f(n, x, *args):
  198. ## libc = CDLL(libc_name)
  199. ## ptr = libc.getpointer('labs', [types.slong], types.slong)
  200. ## chain = ArgChain()
  201. ## chain.arg(n)
  202. ## n = ptr.call(chain, lltype.Signed)
  203. ## return (n, x) + args
  204. ## return None, f, None
  205. def define_compile_framework_1(cls):
  206. # a moving GC. Simple test, works
  207. # without write_barriers and root stack enumeration.
  208. def f(n, x, *args):
  209. y = X()
  210. y.foo = x.foo
  211. n -= y.foo
  212. return (n, x) + args
  213. return None, f, None
  214. def test_compile_framework_1(self):
  215. self.run('compile_framework_1')
  216. def define_compile_framework_2(cls):
  217. # More complex test, requires root stack enumeration but
  218. # not write_barriers.
  219. def f(n, x, *args):
  220. prev = x
  221. for j in range(101): # f() runs 20'000 times, thus allocates
  222. y = X() # a total of 2'020'000 objects
  223. y.foo = prev.foo
  224. prev = y
  225. n -= prev.foo
  226. return (n, x) + args
  227. return None, f, None
  228. def test_compile_framework_2(self):
  229. self.run('compile_framework_2')
  230. def define_compile_framework_3(cls):
  231. # Third version of the test. Really requires write_barriers.
  232. def f(n, x, *args):
  233. x.next = None
  234. for j in range(101): # f() runs 20'000 times, thus allocates
  235. y = X() # a total of 2'020'000 objects
  236. y.foo = j+1
  237. y.next = x.next
  238. x.next = y
  239. check(x.next.foo == 101)
  240. total = 0
  241. y = x
  242. for j in range(101):
  243. y = y.next
  244. total += y.foo
  245. check(not y.next)
  246. check(total == 101*102/2)
  247. n -= x.foo
  248. return (n, x) + args
  249. return None, f, None
  250. def test_compile_framework_3(self):
  251. x_test = X()
  252. x_test.foo = 5
  253. self.run_orig('compile_framework_3', 6, x_test) # check that it does not raise CheckError
  254. self.run('compile_framework_3')
  255. def define_compile_framework_3_extra(cls):
  256. # Extra version of the test, with tons of live vars around the residual
  257. # call that all contain a GC pointer.
  258. @dont_look_inside
  259. def residual(n=26):
  260. x = X()
  261. x.next = X()
  262. x.next.foo = n
  263. return x
  264. #
  265. def before(n, x):
  266. residual(5)
  267. x0 = residual()
  268. x1 = residual()
  269. x2 = residual()
  270. x3 = residual()
  271. x4 = residual()
  272. x5 = residual()
  273. x6 = residual()
  274. x7 = residual()
  275. n *= 19
  276. return n, None, x0, x1, x2, x3, x4, x5, x6, x7, None, None
  277. def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s):
  278. x8 = residual()
  279. x9 = residual()
  280. check(x0.next.foo == 26)
  281. check(x1.next.foo == 26)
  282. check(x2.next.foo == 26)
  283. check(x3.next.foo == 26)
  284. check(x4.next.foo == 26)
  285. check(x5.next.foo == 26)
  286. check(x6.next.foo == 26)
  287. check(x7.next.foo == 26)
  288. check(x8.next.foo == 26)
  289. check(x9.next.foo == 26)
  290. x0, x1, x2, x3, x4, x5, x6, x7 = x7, x4, x6, x5, x3, x2, x9, x8
  291. n -= 1
  292. return n, None, x0, x1, x2, x3, x4, x5, x6, x7, None, None
  293. return before, f, None
  294. def test_compile_framework_3_extra(self):
  295. self.run_orig('compile_framework_3_extra', 6, None) # check that it does not raise CheckError
  296. self.run('compile_framework_3_extra')
  297. def define_compile_framework_4(cls):
  298. # Fourth version of the test, with __del__.
  299. from rpython.rlib.debug import debug_print
  300. class Counter:
  301. cnt = 0
  302. counter = Counter()
  303. class Z:
  304. def __del__(self):
  305. counter.cnt -= 1
  306. def before(n, x):
  307. debug_print('counter.cnt =', counter.cnt)
  308. check(counter.cnt < 5)
  309. counter.cnt = n // x.foo
  310. return n, x, None, None, None, None, None, None, None, None, None, None
  311. def f(n, x, *args):
  312. Z()
  313. n -= x.foo
  314. return (n, x) + args
  315. return before, f, None
  316. def test_compile_framework_4(self):
  317. self.run('compile_framework_4')
  318. def define_compile_framework_5(cls):
  319. # Test string manipulation.
  320. def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s):
  321. n -= x.foo
  322. s += str(n)
  323. return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s
  324. def after(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s):
  325. check(len(s) == 1*5 + 2*45 + 3*450 + 4*500)
  326. return None, f, after
  327. def test_compile_framework_5(self):
  328. self.run('compile_framework_5')
  329. def define_compile_framework_7(cls):
  330. # Array of pointers (test the write barrier for setarrayitem_gc)
  331. def before(n, x):
  332. return n, x, None, None, None, None, None, None, None, None, [X(123)], None
  333. def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s):
  334. if n < 1900:
  335. check(l[0].x == 123)
  336. l = [None] * 16
  337. l[0] = X(123)
  338. l[1] = X(n)
  339. l[2] = X(n+10)
  340. l[3] = X(n+20)
  341. l[4] = X(n+30)
  342. l[5] = X(n+40)
  343. l[6] = X(n+50)
  344. l[7] = X(n+60)
  345. l[8] = X(n+70)
  346. l[9] = X(n+80)
  347. l[10] = X(n+90)
  348. l[11] = X(n+100)
  349. l[12] = X(n+110)
  350. l[13] = X(n+120)
  351. l[14] = X(n+130)
  352. l[15] = X(n+140)
  353. if n < 1800:
  354. check(len(l) == 16)
  355. check(l[0].x == 123)
  356. check(l[1].x == n)
  357. check(l[2].x == n+10)
  358. check(l[3].x == n+20)
  359. check(l[4].x == n+30)
  360. check(l[5].x == n+40)
  361. check(l[6].x == n+50)
  362. check(l[7].x == n+60)
  363. check(l[8].x == n+70)
  364. check(l[9].x == n+80)
  365. check(l[10].x == n+90)
  366. check(l[11].x == n+100)
  367. check(l[12].x == n+110)
  368. check(l[13].x == n+120)
  369. check(l[14].x == n+130)
  370. check(l[15].x == n+140)
  371. n -= x.foo
  372. return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s
  373. def after(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s):
  374. check(len(l) == 16)
  375. check(l[0].x == 123)
  376. check(l[1].x == 2)
  377. check(l[2].x == 12)
  378. check(l[3].x == 22)
  379. check(l[4].x == 32)
  380. check(l[5].x == 42)
  381. check(l[6].x == 52)
  382. check(l[7].x == 62)
  383. check(l[8].x == 72)
  384. check(l[9].x == 82)
  385. check(l[10].x == 92)
  386. check(l[11].x == 102)
  387. check(l[12].x == 112)
  388. check(l[13].x == 122)
  389. check(l[14].x == 132)
  390. check(l[15].x == 142)
  391. return before, f, after
  392. def test_compile_framework_7(self):
  393. self.run('compile_framework_7')
  394. def define_compile_framework_7_interior(cls):
  395. # Array of structs containing pointers (test the write barrier
  396. # for setinteriorfield_gc)
  397. S = lltype.GcStruct('S', ('i', lltype.Signed))
  398. A = lltype.GcArray(lltype.Struct('entry', ('x', lltype.Ptr(S)),
  399. ('y', lltype.Ptr(S)),
  400. ('z', lltype.Ptr(S))))
  401. class Glob:
  402. a = lltype.nullptr(A)
  403. glob = Glob()
  404. #
  405. def make_s(i):
  406. s = lltype.malloc(S)
  407. s.i = i
  408. return s
  409. #
  410. @unroll_safe
  411. def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s):
  412. a = glob.a
  413. if not a:
  414. a = glob.a = lltype.malloc(A, 10)
  415. i = 0
  416. while i < 10:
  417. a[i].x = make_s(n + i * 100 + 1)
  418. a[i].y = make_s(n + i * 100 + 2)
  419. a[i].z = make_s(n + i * 100 + 3)
  420. i += 1
  421. i = 0
  422. while i < 10:
  423. check(a[i].x.i == n + i * 100 + 1)
  424. check(a[i].y.i == n + i * 100 + 2)
  425. check(a[i].z.i == n + i * 100 + 3)
  426. i += 1
  427. n -= x.foo
  428. return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s
  429. return None, f, None
  430. def test_compile_framework_7_interior(self):
  431. self.run('compile_framework_7_interior')
  432. def define_compile_framework_8(cls):
  433. # Array of pointers, of unknown length (test write_barrier_from_array)
  434. def before(n, x):
  435. return n, x, None, None, None, None, None, None, None, None, [X(123)], None
  436. def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s):
  437. if n < 1900:
  438. check(l[0].x == 123)
  439. l = [None] * (16 + (n & 7))
  440. l[0] = X(123)
  441. l[1] = X(n)
  442. l[2] = X(n+10)
  443. l[3] = X(n+20)
  444. l[4] = X(n+30)
  445. l[5] = X(n+40)
  446. l[6] = X(n+50)
  447. l[7] = X(n+60)
  448. l[8] = X(n+70)
  449. l[9] = X(n+80)
  450. l[10] = X(n+90)
  451. l[11] = X(n+100)
  452. l[12] = X(n+110)
  453. l[13] = X(n+120)
  454. l[14] = X(n+130)
  455. l[15] = X(n+140)
  456. if n < 1800:
  457. check(len(l) == 16 + (n & 7))
  458. check(l[0].x == 123)
  459. check(l[1].x == n)
  460. check(l[2].x == n+10)
  461. check(l[3].x == n+20)
  462. check(l[4].x == n+30)
  463. check(l[5].x == n+40)
  464. check(l[6].x == n+50)
  465. check(l[7].x == n+60)
  466. check(l[8].x == n+70)
  467. check(l[9].x == n+80)
  468. check(l[10].x == n+90)
  469. check(l[11].x == n+100)
  470. check(l[12].x == n+110)
  471. check(l[13].x == n+120)
  472. check(l[14].x == n+130)
  473. check(l[15].x == n+140)
  474. n -= x.foo
  475. return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s
  476. def after(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s):
  477. check(len(l) >= 16)
  478. check(l[0].x == 123)
  479. check(l[1].x == 2)
  480. check(l[2].x == 12)
  481. check(l[3].x == 22)
  482. check(l[4].x == 32)
  483. check(l[5].x == 42)
  484. check(l[6].x == 52)
  485. check(l[7].x == 62)
  486. check(l[8].x == 72)
  487. check(l[9].x == 82)
  488. check(l[10].x == 92)
  489. check(l[11].x == 102)
  490. check(l[12].x == 112)
  491. check(l[13].x == 122)
  492. check(l[14].x == 132)
  493. check(l[15].x == 142)
  494. return before, f, after
  495. def test_compile_framework_8(self):
  496. self.run('compile_framework_8')
  497. def define_compile_framework_9(cls):
  498. # Like compile_framework_8, but with variable indexes and large
  499. # arrays, testing the card_marking case
  500. def before(n, x):
  501. return n, x, None, None, None, None, None, None, None, None, [X(123)], None
  502. def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s):
  503. if n < 1900:
  504. check(l[0].x == 123)
  505. num = 512 + (n & 7)
  506. l = [None] * num
  507. l[0] = X(123)
  508. l[1] = X(n)
  509. l[2] = X(n+10)
  510. l[3] = X(n+20)
  511. l[4] = X(n+30)
  512. l[5] = X(n+40)
  513. l[6] = X(n+50)
  514. l[7] = X(n+60)
  515. l[num-8] = X(n+70)
  516. l[num-9] = X(n+80)
  517. l[num-10] = X(n+90)
  518. l[num-11] = X(n+100)
  519. l[-12] = X(n+110)
  520. l[-13] = X(n+120)
  521. l[-14] = X(n+130)
  522. l[-15] = X(n+140)
  523. if n < 1800:
  524. num = 512 + (n & 7)
  525. check(len(l) == num)
  526. check(l[0].x == 123)
  527. check(l[1].x == n)
  528. check(l[2].x == n+10)
  529. check(l[3].x == n+20)
  530. check(l[4].x == n+30)
  531. check(l[5].x == n+40)
  532. check(l[6].x == n+50)
  533. check(l[7].x == n+60)
  534. check(l[num-8].x == n+70)
  535. check(l[num-9].x == n+80)
  536. check(l[num-10].x == n+90)
  537. check(l[num-11].x == n+100)
  538. check(l[-12].x == n+110)
  539. check(l[-13].x == n+120)
  540. check(l[-14].x == n+130)
  541. check(l[-15].x == n+140)
  542. n -= x.foo
  543. return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s
  544. def after(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s):
  545. check(len(l) >= 512)
  546. check(l[0].x == 123)
  547. check(l[1].x == 2)
  548. check(l[2].x == 12)
  549. check(l[3].x == 22)
  550. check(l[4].x == 32)
  551. check(l[5].x == 42)
  552. check(l[6].x == 52)
  553. check(l[7].x == 62)
  554. check(l[-8].x == 72)
  555. check(l[-9].x == 82)
  556. check(l[-10].x == 92)
  557. check(l[-11].x == 102)
  558. check(l[-12].x == 112)
  559. check(l[-13].x == 122)
  560. check(l[-14].x == 132)
  561. check(l[-15].x == 142)
  562. return before, f, after
  563. def test_compile_framework_9(self):
  564. self.run('compile_framework_9')
  565. def define_compile_framework_external_exception_handling(cls):
  566. def before(n, x):
  567. x = X(0)
  568. return n, x, None, None, None, None, None, None, None, None, None, None
  569. @dont_look_inside
  570. def g(x):
  571. if x > 200:
  572. return 2
  573. raise ValueError
  574. @dont_look_inside
  575. def h(x):
  576. if x > 150:
  577. raise ValueError
  578. return 2
  579. def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s):
  580. try:
  581. x.x += g(n)
  582. except ValueError:
  583. x.x += 1
  584. try:
  585. x.x += h(n)
  586. except ValueError:
  587. x.x -= 1
  588. n -= 1
  589. return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s
  590. def after(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s):
  591. check(x.x == 1800 * 2 + 150 * 2 + 200 - 1850)
  592. return before, f, after
  593. def test_compile_framework_external_exception_handling(self):
  594. self.run('compile_framework_external_exception_handling')
  595. def define_compile_framework_bug1(self):
  596. @elidable
  597. def nonmoving():
  598. x = X(1)
  599. for i in range(7):
  600. rgc.collect()
  601. return x
  602. @dont_look_inside
  603. def do_more_stuff():
  604. x = X(5)
  605. for i in range(7):
  606. rgc.collect()
  607. return x
  608. def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s):
  609. x0 = do_more_stuff()
  610. check(nonmoving().x == 1)
  611. n -= 1
  612. return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s
  613. return None, f, None
  614. def test_compile_framework_bug1(self):
  615. self.run('compile_framework_bug1', 200)
  616. def define_compile_framework_vref(self):
  617. from rpython.rlib.jit import virtual_ref, virtual_ref_finish
  618. class A:
  619. pass
  620. glob = A()
  621. def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s):
  622. a = A()
  623. glob.v = vref = virtual_ref(a)
  624. virtual_ref_finish(vref, a)
  625. n -= 1
  626. return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s
  627. return None, f, None
  628. def test_compile_framework_vref(self):
  629. self.run('compile_framework_vref', 200)
  630. def define_compile_framework_float(self):
  631. # test for a bug: the fastpath_malloc does not save and restore
  632. # xmm registers around the actual call to the slow path
  633. class A:
  634. x0 = x1 = x2 = x3 = x4 = x5 = x6 = x7 = 0
  635. @dont_look_inside
  636. def escape1(a):
  637. a.x0 += 0
  638. a.x1 += 6
  639. a.x2 += 12
  640. a.x3 += 18
  641. a.x4 += 24
  642. a.x5 += 30
  643. a.x6 += 36
  644. a.x7 += 42
  645. @dont_look_inside
  646. def escape2(n, f0, f1, f2, f3, f4, f5, f6, f7):
  647. check(f0 == n + 0.0)
  648. check(f1 == n + 0.125)
  649. check(f2 == n + 0.25)
  650. check(f3 == n + 0.375)
  651. check(f4 == n + 0.5)
  652. check(f5 == n + 0.625)
  653. check(f6 == n + 0.75)
  654. check(f7 == n + 0.875)
  655. @unroll_safe
  656. def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s):
  657. i = 0
  658. while i < 42:
  659. m = n + i
  660. f0 = m + 0.0
  661. f1 = m + 0.125
  662. f2 = m + 0.25
  663. f3 = m + 0.375
  664. f4 = m + 0.5
  665. f5 = m + 0.625
  666. f6 = m + 0.75
  667. f7 = m + 0.875
  668. a1 = A()
  669. # at this point, all or most f's are still in xmm registers
  670. escape1(a1)
  671. escape2(m, f0, f1, f2, f3, f4, f5, f6, f7)
  672. i += 1
  673. n -= 1
  674. return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s
  675. return None, f, None
  676. def test_compile_framework_float(self):
  677. self.run('compile_framework_float')
  678. def define_compile_framework_minimal_size_in_nursery(self):
  679. S = lltype.GcStruct('S') # no fields!
  680. T = lltype.GcStruct('T', ('i', lltype.Signed))
  681. @unroll_safe
  682. def f42(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s):
  683. lst1 = []
  684. lst2 = []
  685. i = 0
  686. while i < 42:
  687. s1 = lltype.malloc(S)
  688. t1 = lltype.malloc(T)
  689. t1.i = 10000 + i + n
  690. lst1.append(s1)
  691. lst2.append(t1)
  692. i += 1
  693. i = 0
  694. while i < 42:
  695. check(lst2[i].i == 10000 + i + n)
  696. i += 1
  697. n -= 1
  698. return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s
  699. return None, f42, None
  700. def test_compile_framework_minimal_size_in_nursery(self):
  701. self.run('compile_framework_minimal_size_in_nursery')
  702. def define_compile_framework_call_assembler(self):
  703. S = lltype.GcForwardReference()
  704. S.become(lltype.GcStruct('S', ('s', lltype.Ptr(S))))
  705. driver = JitDriver(greens = [], reds = 'auto', is_recursive=True)
  706. def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s0):
  707. driver.jit_merge_point()
  708. i = 0
  709. prev_s = lltype.nullptr(S)
  710. while i < 100:
  711. s = lltype.malloc(S)
  712. s.s = prev_s
  713. prev_s = s
  714. i += 1
  715. return n - 1, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s0
  716. return None, f, None
  717. def test_compile_framework_call_assembler(self):
  718. self.run('compile_framework_call_assembler')
  719. def define_pinned_simple(cls):
  720. class H:
  721. inst = None
  722. helper = H()
  723. @dont_look_inside
  724. def get_y():
  725. if not helper.inst:
  726. helper.inst = Y()
  727. helper.inst.x = 101
  728. check(rgc.pin(helper.inst))
  729. else:
  730. check(rgc._is_pinned(helper.inst))
  731. return helper.inst
  732. def fn(n, x, *args):
  733. t = get_y()
  734. promote(t)
  735. t.x += 11
  736. n -= 1
  737. return (n, x) + args
  738. return None, fn, None
  739. def test_pinned_simple(self):
  740. self.run('pinned_simple')
  741. def define_pinned_unpin(cls):
  742. class H:
  743. inst = None
  744. pinned = False
  745. count_pinned = 0
  746. count_unpinned = 0
  747. helper = H()
  748. @dont_look_inside
  749. def get_y(n):
  750. if not helper.inst:
  751. helper.inst = Y()
  752. helper.inst.x = 101
  753. helper.pinned = True
  754. check(rgc.pin(helper.inst))
  755. elif n < 100 and helper.pinned:
  756. rgc.unpin(helper.inst)
  757. helper.pinned = False
  758. #
  759. if helper.pinned:
  760. check(rgc._is_pinned(helper.inst))
  761. helper.count_pinned += 1
  762. else:
  763. check(not rgc._is_pinned(helper.inst))
  764. helper.count_unpinned += 1
  765. return helper.inst
  766. def fn(n, x, *args):
  767. t = get_y(n)
  768. promote(t)
  769. check(t.x == 101)
  770. n -= 1
  771. return (n, x) + args
  772. def after(n, x, *args):
  773. check(helper.count_pinned > 0)
  774. check(helper.count_unpinned > 0)
  775. check(not helper.pinned)
  776. return None, fn, after
  777. def test_pinned_unpin(self):
  778. self.run('pinned_unpin')
  779. def define_multiple_pinned(cls):
  780. class H:
  781. inst1 = None
  782. inst2 = None
  783. inst3 = None
  784. initialised = False
  785. helper = H()
  786. @dont_look_inside
  787. def get_instances():
  788. if not helper.initialised:
  789. helper.inst1 = Y()
  790. helper.inst1.x = 101
  791. check(rgc.pin(helper.inst1))
  792. #
  793. helper.inst2 = Y()
  794. helper.inst2.x = 102
  795. #
  796. helper.inst3 = Y()
  797. helper.inst3.x = 103
  798. check(rgc.pin(helper.inst3))
  799. #
  800. helper.initialised = True
  801. #
  802. check(rgc._is_pinned(helper.inst1))
  803. check(not rgc._is_pinned(helper.inst2))
  804. check(rgc._is_pinned(helper.inst3))
  805. return (helper.inst1, helper.inst2, helper.inst3)
  806. def fn(n, x, *args):
  807. inst1, inst2, inst3 = get_instances()
  808. promote(inst1)
  809. promote(inst2)
  810. promote(inst3)
  811. #
  812. check(inst1.x == 101)
  813. check(inst2.x == 102)
  814. check(inst3.x == 103)
  815. #
  816. n -= 1
  817. return (n, x) + args
  818. return None, fn, None
  819. def test_multiple_pinned(self):
  820. self.run('multiple_pinned')