PageRenderTime 52ms CodeModel.GetById 20ms RepoModel.GetById 1ms app.codeStats 0ms

/rpython/jit/backend/test/test_ll_random.py

https://bitbucket.org/pypy/pypy/
Python | 786 lines | 711 code | 56 blank | 19 comment | 117 complexity | afbd8bb06dcec858eb5322bf9d896203 MD5 | raw file
Possible License(s): AGPL-3.0, BSD-3-Clause, Apache-2.0
  1. import py
  2. from rpython.rtyper.lltypesystem import lltype, llmemory, rffi, rstr
  3. from rpython.rtyper import rclass
  4. from rpython.jit.backend.test import test_random
  5. from rpython.jit.backend.test.test_random import getint, getref_base, getref
  6. from rpython.jit.metainterp.resoperation import ResOperation, rop, optypes
  7. from rpython.jit.metainterp.history import ConstInt, ConstPtr, getkind
  8. from rpython.jit.codewriter import heaptracker
  9. from rpython.jit.codewriter.effectinfo import EffectInfo
  10. from rpython.rtyper.annlowlevel import llhelper
  11. from rpython.rlib.rarithmetic import intmask
  12. from rpython.rtyper.llinterp import LLException
  13. class LLtypeOperationBuilder(test_random.OperationBuilder):
  14. HAVE_SHORT_FIELDS = False
  15. def __init__(self, *args, **kw):
  16. test_random.OperationBuilder.__init__(self, *args, **kw)
  17. self.vtable_counter = 0
  18. # note: rstrs and runicodes contain either new local strings, or
  19. # constants. In other words, all BoxPtrs here were created earlier
  20. # by the trace before, and so it should be kind of fine to mutate
  21. # them with strsetitem/unicodesetitem.
  22. self.rstrs = []
  23. self.runicodes = []
  24. self.structure_types = []
  25. self.structure_types_and_vtables = []
  26. def fork(self, cpu, loop, vars):
  27. fork = test_random.OperationBuilder.fork(self, cpu, loop, vars)
  28. fork.structure_types = self.structure_types
  29. fork.structure_types_and_vtables = self.structure_types_and_vtables
  30. return fork
  31. def _choose_ptr_vars(self, from_, type, array_of_structs):
  32. ptrvars = []
  33. for i in range(len(from_)):
  34. v, S = from_[i][:2]
  35. if not isinstance(S, type):
  36. continue
  37. if ((isinstance(S, lltype.Array) and
  38. isinstance(S.OF, lltype.Struct)) == array_of_structs):
  39. ptrvars.append((v, S))
  40. return ptrvars
  41. def get_structptr_var(self, r, must_have_vtable=False, type=lltype.Struct,
  42. array_of_structs=False):
  43. while True:
  44. ptrvars = self._choose_ptr_vars(self.ptrvars, type,
  45. array_of_structs)
  46. if ptrvars and r.random() < 0.8:
  47. v, S = r.choice(ptrvars)
  48. else:
  49. prebuilt_ptr_consts = self._choose_ptr_vars(
  50. self.prebuilt_ptr_consts, type, array_of_structs)
  51. if prebuilt_ptr_consts and r.random() < 0.7:
  52. v, S = r.choice(prebuilt_ptr_consts)
  53. else:
  54. if type is lltype.Struct:
  55. # create a new constant structure
  56. must_have_vtable = must_have_vtable or r.random() < 0.5
  57. p = self.get_random_structure(r,
  58. has_vtable=must_have_vtable)
  59. else:
  60. # create a new constant array
  61. p = self.get_random_array(r,
  62. must_be_array_of_structs=array_of_structs)
  63. S = lltype.typeOf(p).TO
  64. v = ConstPtr(lltype.cast_opaque_ptr(llmemory.GCREF, p))
  65. self.prebuilt_ptr_consts.append((v, S,
  66. self.field_values(p)))
  67. if not (must_have_vtable and S._names[0] != 'parent'):
  68. break
  69. return v, S
  70. def get_arrayptr_var(self, r):
  71. return self.get_structptr_var(r, type=lltype.Array)
  72. def get_random_primitive_type(self, r):
  73. rval = r.random()
  74. if rval < 0.25:
  75. TYPE = lltype.Signed
  76. elif rval < 0.5:
  77. TYPE = lltype.Char
  78. elif rval < 0.75:
  79. TYPE = rffi.UCHAR
  80. else:
  81. TYPE = rffi.SHORT
  82. if not self.HAVE_SHORT_FIELDS:
  83. TYPE = lltype.Signed
  84. return TYPE
  85. def get_random_structure_type(self, r, with_vtable=None, cache=True,
  86. type=lltype.GcStruct):
  87. if cache and self.structure_types and r.random() < 0.5:
  88. return r.choice(self.structure_types)
  89. fields = []
  90. kwds = {}
  91. if with_vtable:
  92. fields.append(('parent', rclass.OBJECT))
  93. kwds['hints'] = {'vtable': with_vtable._obj}
  94. for i in range(r.randrange(1, 5)):
  95. if r.random() < 0.1:
  96. kind = 'r'
  97. TYPE = llmemory.GCREF
  98. else:
  99. kind = 'i'
  100. TYPE = self.get_random_primitive_type(r)
  101. fields.append(('%s%d' % (kind, i), TYPE))
  102. S = type('S%d' % self.counter, *fields, **kwds)
  103. self.counter += 1
  104. if cache:
  105. self.structure_types.append(S)
  106. return S
  107. def get_random_structure_type_and_vtable(self, r):
  108. if self.structure_types_and_vtables and r.random() < 0.5:
  109. return r.choice(self.structure_types_and_vtables)
  110. vtable = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True)
  111. vtable.subclassrange_min = self.vtable_counter
  112. vtable.subclassrange_max = self.vtable_counter
  113. self.vtable_counter += 1
  114. S = self.get_random_structure_type(r, with_vtable=vtable, cache=False)
  115. name = S._name
  116. heaptracker.set_testing_vtable_for_gcstruct(S, vtable, name)
  117. self.structure_types_and_vtables.append((S, vtable))
  118. #
  119. return S, vtable
  120. def get_random_structure(self, r, has_vtable=False):
  121. if has_vtable:
  122. S, vtable = self.get_random_structure_type_and_vtable(r)
  123. p = lltype.malloc(S)
  124. p.parent.typeptr = vtable
  125. else:
  126. S = self.get_random_structure_type(r)
  127. p = lltype.malloc(S)
  128. for fieldname in lltype.typeOf(p).TO._names:
  129. if fieldname != 'parent':
  130. TYPE = getattr(S, fieldname)
  131. setattr(p, fieldname, rffi.cast(TYPE, r.random_integer()))
  132. return p
  133. def get_random_array_type(self, r, can_be_array_of_struct=False,
  134. must_be_array_of_structs=False):
  135. if ((can_be_array_of_struct and r.random() < 0.1) or
  136. must_be_array_of_structs):
  137. TYPE = self.get_random_structure_type(r, cache=False,
  138. type=lltype.Struct)
  139. else:
  140. TYPE = self.get_random_primitive_type(r)
  141. return lltype.GcArray(TYPE)
  142. def get_random_array(self, r, must_be_array_of_structs=False):
  143. A = self.get_random_array_type(r,
  144. must_be_array_of_structs=must_be_array_of_structs)
  145. length = (r.random_integer() // 15) % 300 # length: between 0 and 299
  146. # likely to be small
  147. p = lltype.malloc(A, length)
  148. if isinstance(A.OF, lltype.Primitive):
  149. for i in range(length):
  150. p[i] = rffi.cast(A.OF, r.random_integer())
  151. else:
  152. for i in range(length):
  153. for fname, TP in A.OF._flds.iteritems():
  154. setattr(p[i], fname, rffi.cast(TP, r.random_integer()))
  155. return p
  156. def get_index(self, length, r):
  157. if length == 0:
  158. raise test_random.CannotProduceOperation
  159. v_index = r.choice(self.intvars)
  160. if not (0 <= getint(v_index) < length):
  161. v_index = ConstInt(r.random_integer() % length)
  162. return v_index
  163. def field_values(self, p):
  164. dic = {}
  165. S = lltype.typeOf(p).TO
  166. if isinstance(S, lltype.Struct):
  167. for fieldname in S._names:
  168. if fieldname != 'parent':
  169. dic[fieldname] = getattr(p, fieldname)
  170. else:
  171. assert isinstance(S, lltype.Array)
  172. if isinstance(S.OF, lltype.Struct):
  173. for i in range(len(p)):
  174. item = p[i]
  175. s1 = {}
  176. for fieldname in S.OF._names:
  177. s1[fieldname] = getattr(item, fieldname)
  178. dic[i] = s1
  179. else:
  180. for i in range(len(p)):
  181. dic[i] = p[i]
  182. return dic
  183. def print_loop_prebuilt(self, names, writevar, s):
  184. written = {}
  185. for v, S, fields in self.prebuilt_ptr_consts:
  186. if S not in written:
  187. print >>s, ' %s = lltype.GcStruct(%r,' % (S._name, S._name)
  188. for name in S._names:
  189. if name == 'parent':
  190. print >>s, " ('parent', rclass.OBJECT),"
  191. else:
  192. print >>s, ' (%r, lltype.Signed),'%(name,)
  193. print >>s, ' )'
  194. if S._names[0] == 'parent':
  195. print >>s, ' %s_vtable = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True)' % (S._name,)
  196. written[S] = True
  197. print >>s, ' p = lltype.malloc(%s)' % (S._name,)
  198. if S._names[0] == 'parent':
  199. print >>s, ' p.parent.typeptr = %s_vtable' % (S._name,)
  200. for name, value in fields.items():
  201. print >>s, ' p.%s = %d' % (name, value)
  202. writevar(v, 'preb', 'lltype.cast_opaque_ptr(llmemory.GCREF, p)')
  203. # ____________________________________________________________
  204. def ConstAddr(addr, cpu):
  205. return ConstInt(heaptracker.adr2int(addr))
  206. class GuardClassOperation(test_random.GuardOperation):
  207. def gen_guard(self, builder, r):
  208. ptrvars = [(v, S) for (v, S) in builder.ptrvars
  209. if isinstance(S, lltype.Struct) and
  210. S._names[0] == 'parent']
  211. if not ptrvars:
  212. raise test_random.CannotProduceOperation
  213. v, S = r.choice(ptrvars)
  214. if r.random() < 0.3:
  215. v2, S2 = v, S
  216. else:
  217. v2, S2 = builder.get_structptr_var(r, must_have_vtable=True)
  218. vtable = S._hints['vtable']._as_ptr()
  219. vtable2 = S2._hints['vtable']._as_ptr()
  220. c_vtable2 = ConstAddr(llmemory.cast_ptr_to_adr(vtable2), builder.cpu)
  221. op = ResOperation(self.opnum, [v, c_vtable2], None)
  222. return op, (vtable == vtable2)
  223. class GuardNonNullClassOperation(GuardClassOperation):
  224. def gen_guard(self, builder, r):
  225. if r.random() < 0.5:
  226. return GuardClassOperation.gen_guard(self, builder, r)
  227. else:
  228. NULL = lltype.nullptr(llmemory.GCREF.TO)
  229. op = ResOperation(rop.SAME_AS_R, [ConstPtr(NULL)])
  230. builder.loop.operations.append(op)
  231. v2, S2 = builder.get_structptr_var(r, must_have_vtable=True)
  232. vtable2 = S2._hints['vtable']._as_ptr()
  233. c_vtable2 = ConstAddr(llmemory.cast_ptr_to_adr(vtable2),
  234. builder.cpu)
  235. op = ResOperation(self.opnum, [op, c_vtable2], None)
  236. return op, False
  237. class ZeroPtrFieldOperation(test_random.AbstractOperation):
  238. def field_descr(self, builder, r):
  239. if getattr(builder.cpu, 'is_llgraph', False):
  240. raise test_random.CannotProduceOperation
  241. v, S = builder.get_structptr_var(r, )
  242. names = S._names
  243. if names[0] == 'parent':
  244. names = names[1:]
  245. choice = []
  246. for name in names:
  247. FIELD = getattr(S, name)
  248. if FIELD is lltype.Signed: # xxx should be a gc ptr, but works too
  249. choice.append(name)
  250. if not choice:
  251. raise test_random.CannotProduceOperation
  252. name = r.choice(choice)
  253. descr = builder.cpu.fielddescrof(S, name)
  254. return v, descr.offset
  255. def produce_into(self, builder, r):
  256. v, offset = self.field_descr(builder, r)
  257. builder.do(self.opnum, [v, ConstInt(offset)], None)
  258. class GetFieldOperation(test_random.AbstractOperation):
  259. def field_descr(self, builder, r):
  260. v, S = builder.get_structptr_var(r, )
  261. names = S._names
  262. if names[0] == 'parent':
  263. names = names[1:]
  264. choice = []
  265. kind = optypes[self.opnum]
  266. for name in names:
  267. FIELD = getattr(S, name)
  268. if not isinstance(FIELD, lltype.Ptr):
  269. if kind == 'n' or getkind(FIELD)[0] == kind:
  270. choice.append(name)
  271. if not choice:
  272. raise test_random.CannotProduceOperation
  273. name = r.choice(choice)
  274. descr = builder.cpu.fielddescrof(S, name)
  275. descr._random_info = 'cpu.fielddescrof(..., %r)' % (name,)
  276. descr._random_type = S
  277. TYPE = getattr(S, name)
  278. return v, descr, TYPE
  279. def produce_into(self, builder, r):
  280. while True:
  281. try:
  282. v, descr, _ = self.field_descr(builder, r)
  283. self.put(builder, [v], descr)
  284. except lltype.UninitializedMemoryAccess:
  285. continue
  286. break
  287. class GetInteriorFieldOperation(test_random.AbstractOperation):
  288. def field_descr(self, builder, r):
  289. v, A = builder.get_structptr_var(r, type=lltype.Array,
  290. array_of_structs=True)
  291. array = getref(lltype.Ptr(A), v)
  292. v_index = builder.get_index(len(array), r)
  293. choice = []
  294. for name in A.OF._names:
  295. FIELD = getattr(A.OF, name)
  296. if not isinstance(FIELD, lltype.Ptr):
  297. choice.append(name)
  298. if not choice:
  299. raise test_random.CannotProduceOperation
  300. name = r.choice(choice)
  301. descr = builder.cpu.interiorfielddescrof(A, name)
  302. descr._random_info = 'cpu.interiorfielddescrof(..., %r)' % (name,)
  303. descr._random_type = A
  304. TYPE = getattr(A.OF, name)
  305. return v, v_index, descr, TYPE
  306. def produce_into(self, builder, r):
  307. while True:
  308. try:
  309. v, v_index, descr, _ = self.field_descr(builder, r)
  310. self.put(builder, [v, v_index], descr)
  311. except lltype.UninitializedMemoryAccess:
  312. continue
  313. break
  314. class SetFieldOperation(GetFieldOperation):
  315. def produce_into(self, builder, r):
  316. v, descr, TYPE = self.field_descr(builder, r)
  317. while True:
  318. if r.random() < 0.3:
  319. w = ConstInt(r.random_integer())
  320. else:
  321. w = r.choice(builder.intvars)
  322. value = getint(w)
  323. if rffi.cast(lltype.Signed, rffi.cast(TYPE, value)) == value:
  324. break
  325. builder.do(self.opnum, [v, w], descr)
  326. class SetInteriorFieldOperation(GetInteriorFieldOperation):
  327. def produce_into(self, builder, r):
  328. v, v_index, descr, TYPE = self.field_descr(builder, r)
  329. while True:
  330. if r.random() < 0.3:
  331. w = ConstInt(r.random_integer())
  332. else:
  333. w = r.choice(builder.intvars)
  334. value = getint(w)
  335. if rffi.cast(lltype.Signed, rffi.cast(TYPE, value)) == value:
  336. break
  337. builder.do(self.opnum, [v, v_index, w], descr)
  338. class NewOperation(test_random.AbstractOperation):
  339. def size_descr(self, builder, S, *vtable):
  340. descr = builder.cpu.sizeof(S, *vtable)
  341. descr._random_info = 'cpu.sizeof(...)'
  342. descr._random_type = S
  343. return descr
  344. def produce_into(self, builder, r):
  345. if self.opnum == rop.NEW_WITH_VTABLE:
  346. S, vtable = builder.get_random_structure_type_and_vtable(r)
  347. descr = self.size_descr(builder, S, vtable)
  348. else:
  349. S = builder.get_random_structure_type(r)
  350. descr = self.size_descr(builder, S)
  351. v_ptr = builder.do(self.opnum, [], descr)
  352. builder.ptrvars.append((v_ptr, S))
  353. class ArrayOperation(test_random.AbstractOperation):
  354. def array_descr(self, builder, A):
  355. descr = builder.cpu.arraydescrof(A)
  356. descr._random_info = 'cpu.arraydescrof(...)'
  357. descr._random_type = A
  358. return descr
  359. class GetArrayItemOperation(ArrayOperation):
  360. def field_descr(self, builder, r):
  361. v, A = builder.get_arrayptr_var(r)
  362. array = getref(lltype.Ptr(A), v)
  363. v_index = builder.get_index(len(array), r)
  364. descr = self.array_descr(builder, A)
  365. return v, A, v_index, descr
  366. def produce_into(self, builder, r):
  367. while True:
  368. try:
  369. v, _, v_index, descr = self.field_descr(builder, r)
  370. self.put(builder, [v, v_index], descr)
  371. except lltype.UninitializedMemoryAccess:
  372. continue
  373. break
  374. class SetArrayItemOperation(GetArrayItemOperation):
  375. def produce_into(self, builder, r):
  376. v, A, v_index, descr = self.field_descr(builder, r)
  377. while True:
  378. if r.random() < 0.3:
  379. w = ConstInt(r.random_integer())
  380. else:
  381. w = r.choice(builder.intvars)
  382. value = getint(w)
  383. if rffi.cast(lltype.Signed, rffi.cast(A.OF, value)) == value:
  384. break
  385. builder.do(self.opnum, [v, v_index, w], descr)
  386. class NewArrayOperation(ArrayOperation):
  387. def produce_into(self, builder, r):
  388. A = builder.get_random_array_type(r, can_be_array_of_struct=True)
  389. v_size = builder.get_index(300, r)
  390. v_ptr = builder.do(self.opnum, [v_size], self.array_descr(builder, A))
  391. builder.ptrvars.append((v_ptr, A))
  392. class ArrayLenOperation(ArrayOperation):
  393. def produce_into(self, builder, r):
  394. v, A = builder.get_arrayptr_var(r)
  395. descr = self.array_descr(builder, A)
  396. self.put(builder, [v], descr)
  397. class _UnicodeOperation:
  398. builder_cache = "runicodes"
  399. struct = rstr.UNICODE
  400. ptr = lltype.Ptr(struct)
  401. alloc = staticmethod(rstr.mallocunicode)
  402. # XXX This should really be runicode.MAXUNICODE, but then
  403. # lltype.cast_primitive complains.
  404. max = py.std.sys.maxunicode
  405. primitive = lltype.UniChar
  406. set_char = rop.UNICODESETITEM
  407. class _StrOperation:
  408. builder_cache = "rstrs"
  409. struct = rstr.STR
  410. ptr = lltype.Ptr(struct)
  411. alloc = staticmethod(rstr.mallocstr)
  412. max = 255
  413. primitive = lltype.Char
  414. set_char = rop.STRSETITEM
  415. class NewSeqOperation(test_random.AbstractOperation):
  416. def produce_into(self, builder, r):
  417. v_length = builder.get_index(10, r)
  418. v_ptr = builder.do(self.opnum, [v_length])
  419. getattr(builder, self.builder_cache).append(v_ptr)
  420. # Initialize the string. Is there a better way to do this?
  421. for i in range(getint(v_length)):
  422. v_index = ConstInt(i)
  423. v_char = ConstInt(r.random_integer() % self.max)
  424. builder.do(self.set_char, [v_ptr, v_index, v_char])
  425. class NewStrOperation(NewSeqOperation, _StrOperation):
  426. pass
  427. class NewUnicodeOperation(NewSeqOperation, _UnicodeOperation):
  428. pass
  429. class AbstractStringOperation(test_random.AbstractOperation):
  430. def get_string(self, builder, r):
  431. current = getattr(builder, self.builder_cache)
  432. if current and r.random() < .8:
  433. v_string = r.choice(current)
  434. string = getref(self.ptr, v_string)
  435. else:
  436. string = self.alloc(getint(builder.get_index(500, r)))
  437. v_string = ConstPtr(lltype.cast_opaque_ptr(llmemory.GCREF, string))
  438. current.append(v_string)
  439. for i in range(len(string.chars)):
  440. char = r.random_integer() % self.max
  441. string.chars[i] = lltype.cast_primitive(self.primitive, char)
  442. return v_string
  443. class AbstractGetItemOperation(AbstractStringOperation):
  444. def produce_into(self, builder, r):
  445. v_string = self.get_string(builder, r)
  446. v_index = builder.get_index(len(getref(self.ptr, v_string).chars), r)
  447. builder.do(self.opnum, [v_string, v_index])
  448. class AbstractSetItemOperation(AbstractStringOperation):
  449. def produce_into(self, builder, r):
  450. v_string = self.get_string(builder, r)
  451. if isinstance(v_string, ConstPtr):
  452. raise test_random.CannotProduceOperation # setitem(Const, ...)
  453. v_index = builder.get_index(len(getref(self.ptr, v_string).chars), r)
  454. v_target = ConstInt(r.random_integer() % self.max)
  455. builder.do(self.opnum, [v_string, v_index, v_target])
  456. class AbstractStringLenOperation(AbstractStringOperation):
  457. def produce_into(self, builder, r):
  458. v_string = self.get_string(builder, r)
  459. builder.do(self.opnum, [v_string])
  460. class AbstractCopyContentOperation(AbstractStringOperation):
  461. def produce_into(self, builder, r):
  462. v_srcstring = self.get_string(builder, r)
  463. v_dststring = self.get_string(builder, r)
  464. src = getref(self.ptr, v_srcstring)
  465. dst = getref(self.ptr, v_dststring)
  466. if src == dst: # because it's not a
  467. raise test_random.CannotProduceOperation # memmove(), but memcpy()
  468. srclen = len(src.chars)
  469. dstlen = len(dst.chars)
  470. v_length = builder.get_index(min(srclen, dstlen), r)
  471. v_srcstart = builder.get_index(srclen - getint(v_length) + 1, r)
  472. v_dststart = builder.get_index(dstlen - getint(v_length) + 1, r)
  473. builder.do(self.opnum, [v_srcstring, v_dststring,
  474. v_srcstart, v_dststart, v_length])
  475. class StrGetItemOperation(AbstractGetItemOperation, _StrOperation):
  476. pass
  477. class UnicodeGetItemOperation(AbstractGetItemOperation, _UnicodeOperation):
  478. pass
  479. class StrSetItemOperation(AbstractSetItemOperation, _StrOperation):
  480. pass
  481. class UnicodeSetItemOperation(AbstractSetItemOperation, _UnicodeOperation):
  482. pass
  483. class StrLenOperation(AbstractStringLenOperation, _StrOperation):
  484. pass
  485. class UnicodeLenOperation(AbstractStringLenOperation, _UnicodeOperation):
  486. pass
  487. class CopyStrContentOperation(AbstractCopyContentOperation, _StrOperation):
  488. pass
  489. class CopyUnicodeContentOperation(AbstractCopyContentOperation,
  490. _UnicodeOperation):
  491. pass
  492. # there are five options in total:
  493. # 1. non raising call and guard_no_exception
  494. # 2. raising call and guard_exception
  495. # 3. raising call and wrong guard_exception
  496. # 4. raising call and guard_no_exception
  497. # 5. non raising call and guard_exception
  498. # (6. test of a cond_call, always non-raising and guard_no_exception)
  499. class BaseCallOperation(test_random.AbstractOperation):
  500. def non_raising_func_code(self, builder, r):
  501. subset = builder.subset_of_intvars(r)
  502. funcargs = ", ".join(['arg_%d' % i for i in range(len(subset))])
  503. sum = "intmask(%s)" % " + ".join(
  504. ['arg_%d' % i for i in range(len(subset))] + ['42'])
  505. if self.opnum == rop.CALL_I:
  506. result = 'sum'
  507. elif self.opnum == rop.CALL_F:
  508. result = 'float(sum)'
  509. elif self.opnum == rop.CALL_N:
  510. result = ''
  511. else:
  512. raise AssertionError(self.opnum)
  513. code = py.code.Source("""
  514. def f(%s):
  515. sum = %s
  516. return %s
  517. """ % (funcargs, sum, result)).compile()
  518. d = {'intmask' : intmask}
  519. exec code in d
  520. return subset, d['f']
  521. def raising_func_code(self, builder, r):
  522. subset = builder.subset_of_intvars(r)
  523. funcargs = ", ".join(['arg_%d' % i for i in range(len(subset))])
  524. S, v = builder.get_structptr_var(r, must_have_vtable=True)
  525. code = py.code.Source("""
  526. def f(%s):
  527. raise LLException(vtable, ptr)
  528. """ % funcargs).compile()
  529. vtableptr = v._hints['vtable']._as_ptr()
  530. d = {
  531. 'ptr': getref_base(S),
  532. 'vtable' : vtableptr,
  533. 'LLException' : LLException,
  534. }
  535. exec code in d
  536. return subset, d['f'], vtableptr
  537. def getresulttype(self):
  538. if self.opnum == rop.CALL_I:
  539. return lltype.Signed
  540. elif self.opnum == rop.CALL_F:
  541. return lltype.Float
  542. elif self.opnum == rop.CALL_N or self.opnum == rop.COND_CALL:
  543. return lltype.Void
  544. else:
  545. raise AssertionError(self.opnum)
  546. def getcalldescr(self, builder, TP):
  547. assert TP.RESULT == self.getresulttype()
  548. ef = EffectInfo.MOST_GENERAL
  549. return builder.cpu.calldescrof(TP, TP.ARGS, TP.RESULT, ef)
  550. # 1. non raising call and guard_no_exception
  551. class CallOperation(BaseCallOperation):
  552. def produce_into(self, builder, r):
  553. fail_subset = builder.subset_of_intvars(r)
  554. subset, f = self.non_raising_func_code(builder, r)
  555. RES = self.getresulttype()
  556. TP = lltype.FuncType([lltype.Signed] * len(subset), RES)
  557. ptr = llhelper(lltype.Ptr(TP), f)
  558. c_addr = ConstAddr(llmemory.cast_ptr_to_adr(ptr), builder.cpu)
  559. args = [c_addr] + subset
  560. descr = self.getcalldescr(builder, TP)
  561. self.put(builder, args, descr)
  562. op = ResOperation(rop.GUARD_NO_EXCEPTION, [],
  563. descr=builder.getfaildescr())
  564. op.setfailargs(fail_subset)
  565. builder.loop.operations.append(op)
  566. # 5. Non raising-call and GUARD_EXCEPTION
  567. class CallOperationException(BaseCallOperation):
  568. def produce_into(self, builder, r):
  569. subset, f = self.non_raising_func_code(builder, r)
  570. RES = self.getresulttype()
  571. TP = lltype.FuncType([lltype.Signed] * len(subset), RES)
  572. ptr = llhelper(lltype.Ptr(TP), f)
  573. c_addr = ConstAddr(llmemory.cast_ptr_to_adr(ptr), builder.cpu)
  574. args = [c_addr] + subset
  575. descr = self.getcalldescr(builder, TP)
  576. self.put(builder, args, descr)
  577. _, vtableptr = builder.get_random_structure_type_and_vtable(r)
  578. exc_box = ConstAddr(llmemory.cast_ptr_to_adr(vtableptr), builder.cpu)
  579. op = ResOperation(rop.GUARD_EXCEPTION, [exc_box],
  580. descr=builder.getfaildescr())
  581. op.setfailargs(builder.subset_of_intvars(r))
  582. op._exc_box = None
  583. builder.should_fail_by = op
  584. builder.guard_op = op
  585. builder.loop.operations.append(op)
  586. # 2. raising call and guard_exception
  587. class RaisingCallOperation(BaseCallOperation):
  588. def produce_into(self, builder, r):
  589. fail_subset = builder.subset_of_intvars(r)
  590. subset, f, exc = self.raising_func_code(builder, r)
  591. TP = lltype.FuncType([lltype.Signed] * len(subset), lltype.Void)
  592. ptr = llhelper(lltype.Ptr(TP), f)
  593. c_addr = ConstAddr(llmemory.cast_ptr_to_adr(ptr), builder.cpu)
  594. args = [c_addr] + subset
  595. descr = self.getcalldescr(builder, TP)
  596. self.put(builder, args, descr)
  597. exc_box = ConstAddr(llmemory.cast_ptr_to_adr(exc), builder.cpu)
  598. op = ResOperation(rop.GUARD_EXCEPTION, [exc_box],
  599. descr=builder.getfaildescr())
  600. op.setfailargs(fail_subset)
  601. builder.loop.operations.append(op)
  602. # 4. raising call and guard_no_exception
  603. class RaisingCallOperationGuardNoException(BaseCallOperation):
  604. def produce_into(self, builder, r):
  605. subset, f, exc = self.raising_func_code(builder, r)
  606. TP = lltype.FuncType([lltype.Signed] * len(subset), lltype.Void)
  607. ptr = llhelper(lltype.Ptr(TP), f)
  608. c_addr = ConstAddr(llmemory.cast_ptr_to_adr(ptr), builder.cpu)
  609. args = [c_addr] + subset
  610. descr = self.getcalldescr(builder, TP)
  611. self.put(builder, args, descr)
  612. op = ResOperation(rop.GUARD_NO_EXCEPTION, [],
  613. descr=builder.getfaildescr())
  614. op._exc_box = ConstAddr(llmemory.cast_ptr_to_adr(exc), builder.cpu)
  615. op.setfailargs(builder.subset_of_intvars(r))
  616. builder.should_fail_by = op
  617. builder.guard_op = op
  618. builder.loop.operations.append(op)
  619. # 3. raising call and wrong guard_exception
  620. class RaisingCallOperationWrongGuardException(BaseCallOperation):
  621. def produce_into(self, builder, r):
  622. subset, f, exc = self.raising_func_code(builder, r)
  623. TP = lltype.FuncType([lltype.Signed] * len(subset), lltype.Void)
  624. ptr = llhelper(lltype.Ptr(TP), f)
  625. c_addr = ConstAddr(llmemory.cast_ptr_to_adr(ptr), builder.cpu)
  626. args = [c_addr] + subset
  627. descr = self.getcalldescr(builder, TP)
  628. self.put(builder, args, descr)
  629. while True:
  630. _, vtableptr = builder.get_random_structure_type_and_vtable(r)
  631. if vtableptr != exc:
  632. break
  633. other_box = ConstAddr(llmemory.cast_ptr_to_adr(vtableptr), builder.cpu)
  634. op = ResOperation(rop.GUARD_EXCEPTION, [other_box],
  635. descr=builder.getfaildescr())
  636. op._exc_box = ConstAddr(llmemory.cast_ptr_to_adr(exc), builder.cpu)
  637. op.setfailargs(builder.subset_of_intvars(r))
  638. builder.should_fail_by = op
  639. builder.guard_op = op
  640. builder.loop.operations.append(op)
  641. # 6. a conditional call (for now always with no exception raised)
  642. class CondCallOperation(BaseCallOperation):
  643. def produce_into(self, builder, r):
  644. fail_subset = builder.subset_of_intvars(r)
  645. v_cond = builder.get_bool_var(r)
  646. subset = builder.subset_of_intvars(r)[:4]
  647. for i in range(len(subset)):
  648. if r.random() < 0.35:
  649. subset[i] = ConstInt(r.random_integer())
  650. #
  651. seen = []
  652. def call_me(*args):
  653. if len(seen) == 0:
  654. seen.append(args)
  655. else:
  656. assert seen[0] == args
  657. #
  658. TP = lltype.FuncType([lltype.Signed] * len(subset), lltype.Void)
  659. ptr = llhelper(lltype.Ptr(TP), call_me)
  660. c_addr = ConstAddr(llmemory.cast_ptr_to_adr(ptr), builder.cpu)
  661. args = [v_cond, c_addr] + subset
  662. descr = self.getcalldescr(builder, TP)
  663. self.put(builder, args, descr)
  664. op = ResOperation(rop.GUARD_NO_EXCEPTION, [],
  665. descr=builder.getfaildescr())
  666. op.setfailargs(fail_subset)
  667. builder.loop.operations.append(op)
  668. # ____________________________________________________________
  669. OPERATIONS = test_random.OPERATIONS[:]
  670. for i in range(4): # make more common
  671. OPERATIONS.append(GetFieldOperation(rop.GETFIELD_GC_I))
  672. OPERATIONS.append(GetFieldOperation(rop.GETFIELD_GC_I))
  673. OPERATIONS.append(GetInteriorFieldOperation(rop.GETINTERIORFIELD_GC_I))
  674. OPERATIONS.append(GetInteriorFieldOperation(rop.GETINTERIORFIELD_GC_I))
  675. OPERATIONS.append(SetFieldOperation(rop.SETFIELD_GC))
  676. OPERATIONS.append(SetInteriorFieldOperation(rop.SETINTERIORFIELD_GC))
  677. OPERATIONS.append(NewOperation(rop.NEW))
  678. OPERATIONS.append(NewOperation(rop.NEW_WITH_VTABLE))
  679. OPERATIONS.append(GetArrayItemOperation(rop.GETARRAYITEM_GC_I))
  680. OPERATIONS.append(GetArrayItemOperation(rop.GETARRAYITEM_GC_I))
  681. OPERATIONS.append(SetArrayItemOperation(rop.SETARRAYITEM_GC))
  682. OPERATIONS.append(NewArrayOperation(rop.NEW_ARRAY_CLEAR))
  683. OPERATIONS.append(ArrayLenOperation(rop.ARRAYLEN_GC))
  684. OPERATIONS.append(NewStrOperation(rop.NEWSTR))
  685. OPERATIONS.append(NewUnicodeOperation(rop.NEWUNICODE))
  686. OPERATIONS.append(StrGetItemOperation(rop.STRGETITEM))
  687. OPERATIONS.append(UnicodeGetItemOperation(rop.UNICODEGETITEM))
  688. OPERATIONS.append(StrSetItemOperation(rop.STRSETITEM))
  689. OPERATIONS.append(UnicodeSetItemOperation(rop.UNICODESETITEM))
  690. OPERATIONS.append(StrLenOperation(rop.STRLEN))
  691. OPERATIONS.append(UnicodeLenOperation(rop.UNICODELEN))
  692. OPERATIONS.append(CopyStrContentOperation(rop.COPYSTRCONTENT))
  693. OPERATIONS.append(CopyUnicodeContentOperation(rop.COPYUNICODECONTENT))
  694. for i in range(2):
  695. OPERATIONS.append(GuardClassOperation(rop.GUARD_CLASS))
  696. OPERATIONS.append(CondCallOperation(rop.COND_CALL))
  697. OPERATIONS.append(RaisingCallOperation(rop.CALL_N))
  698. OPERATIONS.append(RaisingCallOperationGuardNoException(rop.CALL_N))
  699. OPERATIONS.append(RaisingCallOperationWrongGuardException(rop.CALL_N))
  700. OPERATIONS.append(GuardNonNullClassOperation(rop.GUARD_NONNULL_CLASS))
  701. for _opnum in [rop.CALL_I, rop.CALL_F, rop.CALL_N]:
  702. OPERATIONS.append(CallOperation(_opnum))
  703. OPERATIONS.append(CallOperationException(_opnum))
  704. LLtypeOperationBuilder.OPERATIONS = OPERATIONS
  705. # ____________________________________________________________
  706. def test_ll_random_function():
  707. test_random.test_random_function(LLtypeOperationBuilder)