/rpython/jit/backend/test/test_ll_random.py
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
- import py
- from rpython.rtyper.lltypesystem import lltype, llmemory, rffi, rstr
- from rpython.rtyper import rclass
- from rpython.jit.backend.test import test_random
- from rpython.jit.backend.test.test_random import getint, getref_base, getref
- from rpython.jit.metainterp.resoperation import ResOperation, rop, optypes
- from rpython.jit.metainterp.history import ConstInt, ConstPtr, getkind
- from rpython.jit.codewriter import heaptracker
- from rpython.jit.codewriter.effectinfo import EffectInfo
- from rpython.rtyper.annlowlevel import llhelper
- from rpython.rlib.rarithmetic import intmask
- from rpython.rtyper.llinterp import LLException
- class LLtypeOperationBuilder(test_random.OperationBuilder):
- HAVE_SHORT_FIELDS = False
- def __init__(self, *args, **kw):
- test_random.OperationBuilder.__init__(self, *args, **kw)
- self.vtable_counter = 0
- # note: rstrs and runicodes contain either new local strings, or
- # constants. In other words, all BoxPtrs here were created earlier
- # by the trace before, and so it should be kind of fine to mutate
- # them with strsetitem/unicodesetitem.
- self.rstrs = []
- self.runicodes = []
- self.structure_types = []
- self.structure_types_and_vtables = []
- def fork(self, cpu, loop, vars):
- fork = test_random.OperationBuilder.fork(self, cpu, loop, vars)
- fork.structure_types = self.structure_types
- fork.structure_types_and_vtables = self.structure_types_and_vtables
- return fork
- def _choose_ptr_vars(self, from_, type, array_of_structs):
- ptrvars = []
- for i in range(len(from_)):
- v, S = from_[i][:2]
- if not isinstance(S, type):
- continue
- if ((isinstance(S, lltype.Array) and
- isinstance(S.OF, lltype.Struct)) == array_of_structs):
- ptrvars.append((v, S))
- return ptrvars
- def get_structptr_var(self, r, must_have_vtable=False, type=lltype.Struct,
- array_of_structs=False):
- while True:
- ptrvars = self._choose_ptr_vars(self.ptrvars, type,
- array_of_structs)
- if ptrvars and r.random() < 0.8:
- v, S = r.choice(ptrvars)
- else:
- prebuilt_ptr_consts = self._choose_ptr_vars(
- self.prebuilt_ptr_consts, type, array_of_structs)
- if prebuilt_ptr_consts and r.random() < 0.7:
- v, S = r.choice(prebuilt_ptr_consts)
- else:
- if type is lltype.Struct:
- # create a new constant structure
- must_have_vtable = must_have_vtable or r.random() < 0.5
- p = self.get_random_structure(r,
- has_vtable=must_have_vtable)
- else:
- # create a new constant array
- p = self.get_random_array(r,
- must_be_array_of_structs=array_of_structs)
- S = lltype.typeOf(p).TO
- v = ConstPtr(lltype.cast_opaque_ptr(llmemory.GCREF, p))
- self.prebuilt_ptr_consts.append((v, S,
- self.field_values(p)))
- if not (must_have_vtable and S._names[0] != 'parent'):
- break
- return v, S
- def get_arrayptr_var(self, r):
- return self.get_structptr_var(r, type=lltype.Array)
- def get_random_primitive_type(self, r):
- rval = r.random()
- if rval < 0.25:
- TYPE = lltype.Signed
- elif rval < 0.5:
- TYPE = lltype.Char
- elif rval < 0.75:
- TYPE = rffi.UCHAR
- else:
- TYPE = rffi.SHORT
- if not self.HAVE_SHORT_FIELDS:
- TYPE = lltype.Signed
- return TYPE
- def get_random_structure_type(self, r, with_vtable=None, cache=True,
- type=lltype.GcStruct):
- if cache and self.structure_types and r.random() < 0.5:
- return r.choice(self.structure_types)
- fields = []
- kwds = {}
- if with_vtable:
- fields.append(('parent', rclass.OBJECT))
- kwds['hints'] = {'vtable': with_vtable._obj}
- for i in range(r.randrange(1, 5)):
- if r.random() < 0.1:
- kind = 'r'
- TYPE = llmemory.GCREF
- else:
- kind = 'i'
- TYPE = self.get_random_primitive_type(r)
- fields.append(('%s%d' % (kind, i), TYPE))
- S = type('S%d' % self.counter, *fields, **kwds)
- self.counter += 1
- if cache:
- self.structure_types.append(S)
- return S
- def get_random_structure_type_and_vtable(self, r):
- if self.structure_types_and_vtables and r.random() < 0.5:
- return r.choice(self.structure_types_and_vtables)
- vtable = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True)
- vtable.subclassrange_min = self.vtable_counter
- vtable.subclassrange_max = self.vtable_counter
- self.vtable_counter += 1
- S = self.get_random_structure_type(r, with_vtable=vtable, cache=False)
- name = S._name
- heaptracker.set_testing_vtable_for_gcstruct(S, vtable, name)
- self.structure_types_and_vtables.append((S, vtable))
- #
- return S, vtable
- def get_random_structure(self, r, has_vtable=False):
- if has_vtable:
- S, vtable = self.get_random_structure_type_and_vtable(r)
- p = lltype.malloc(S)
- p.parent.typeptr = vtable
- else:
- S = self.get_random_structure_type(r)
- p = lltype.malloc(S)
- for fieldname in lltype.typeOf(p).TO._names:
- if fieldname != 'parent':
- TYPE = getattr(S, fieldname)
- setattr(p, fieldname, rffi.cast(TYPE, r.random_integer()))
- return p
- def get_random_array_type(self, r, can_be_array_of_struct=False,
- must_be_array_of_structs=False):
- if ((can_be_array_of_struct and r.random() < 0.1) or
- must_be_array_of_structs):
- TYPE = self.get_random_structure_type(r, cache=False,
- type=lltype.Struct)
- else:
- TYPE = self.get_random_primitive_type(r)
- return lltype.GcArray(TYPE)
- def get_random_array(self, r, must_be_array_of_structs=False):
- A = self.get_random_array_type(r,
- must_be_array_of_structs=must_be_array_of_structs)
- length = (r.random_integer() // 15) % 300 # length: between 0 and 299
- # likely to be small
- p = lltype.malloc(A, length)
- if isinstance(A.OF, lltype.Primitive):
- for i in range(length):
- p[i] = rffi.cast(A.OF, r.random_integer())
- else:
- for i in range(length):
- for fname, TP in A.OF._flds.iteritems():
- setattr(p[i], fname, rffi.cast(TP, r.random_integer()))
- return p
- def get_index(self, length, r):
- if length == 0:
- raise test_random.CannotProduceOperation
- v_index = r.choice(self.intvars)
- if not (0 <= getint(v_index) < length):
- v_index = ConstInt(r.random_integer() % length)
- return v_index
- def field_values(self, p):
- dic = {}
- S = lltype.typeOf(p).TO
- if isinstance(S, lltype.Struct):
- for fieldname in S._names:
- if fieldname != 'parent':
- dic[fieldname] = getattr(p, fieldname)
- else:
- assert isinstance(S, lltype.Array)
- if isinstance(S.OF, lltype.Struct):
- for i in range(len(p)):
- item = p[i]
- s1 = {}
- for fieldname in S.OF._names:
- s1[fieldname] = getattr(item, fieldname)
- dic[i] = s1
- else:
- for i in range(len(p)):
- dic[i] = p[i]
- return dic
- def print_loop_prebuilt(self, names, writevar, s):
- written = {}
- for v, S, fields in self.prebuilt_ptr_consts:
- if S not in written:
- print >>s, ' %s = lltype.GcStruct(%r,' % (S._name, S._name)
- for name in S._names:
- if name == 'parent':
- print >>s, " ('parent', rclass.OBJECT),"
- else:
- print >>s, ' (%r, lltype.Signed),'%(name,)
- print >>s, ' )'
- if S._names[0] == 'parent':
- print >>s, ' %s_vtable = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True)' % (S._name,)
- written[S] = True
- print >>s, ' p = lltype.malloc(%s)' % (S._name,)
- if S._names[0] == 'parent':
- print >>s, ' p.parent.typeptr = %s_vtable' % (S._name,)
- for name, value in fields.items():
- print >>s, ' p.%s = %d' % (name, value)
- writevar(v, 'preb', 'lltype.cast_opaque_ptr(llmemory.GCREF, p)')
- # ____________________________________________________________
- def ConstAddr(addr, cpu):
- return ConstInt(heaptracker.adr2int(addr))
- class GuardClassOperation(test_random.GuardOperation):
- def gen_guard(self, builder, r):
- ptrvars = [(v, S) for (v, S) in builder.ptrvars
- if isinstance(S, lltype.Struct) and
- S._names[0] == 'parent']
- if not ptrvars:
- raise test_random.CannotProduceOperation
- v, S = r.choice(ptrvars)
- if r.random() < 0.3:
- v2, S2 = v, S
- else:
- v2, S2 = builder.get_structptr_var(r, must_have_vtable=True)
- vtable = S._hints['vtable']._as_ptr()
- vtable2 = S2._hints['vtable']._as_ptr()
- c_vtable2 = ConstAddr(llmemory.cast_ptr_to_adr(vtable2), builder.cpu)
- op = ResOperation(self.opnum, [v, c_vtable2], None)
- return op, (vtable == vtable2)
- class GuardNonNullClassOperation(GuardClassOperation):
- def gen_guard(self, builder, r):
- if r.random() < 0.5:
- return GuardClassOperation.gen_guard(self, builder, r)
- else:
- NULL = lltype.nullptr(llmemory.GCREF.TO)
- op = ResOperation(rop.SAME_AS_R, [ConstPtr(NULL)])
- builder.loop.operations.append(op)
- v2, S2 = builder.get_structptr_var(r, must_have_vtable=True)
- vtable2 = S2._hints['vtable']._as_ptr()
- c_vtable2 = ConstAddr(llmemory.cast_ptr_to_adr(vtable2),
- builder.cpu)
- op = ResOperation(self.opnum, [op, c_vtable2], None)
- return op, False
- class ZeroPtrFieldOperation(test_random.AbstractOperation):
- def field_descr(self, builder, r):
- if getattr(builder.cpu, 'is_llgraph', False):
- raise test_random.CannotProduceOperation
- v, S = builder.get_structptr_var(r, )
- names = S._names
- if names[0] == 'parent':
- names = names[1:]
- choice = []
- for name in names:
- FIELD = getattr(S, name)
- if FIELD is lltype.Signed: # xxx should be a gc ptr, but works too
- choice.append(name)
- if not choice:
- raise test_random.CannotProduceOperation
- name = r.choice(choice)
- descr = builder.cpu.fielddescrof(S, name)
- return v, descr.offset
- def produce_into(self, builder, r):
- v, offset = self.field_descr(builder, r)
- builder.do(self.opnum, [v, ConstInt(offset)], None)
- class GetFieldOperation(test_random.AbstractOperation):
- def field_descr(self, builder, r):
- v, S = builder.get_structptr_var(r, )
- names = S._names
- if names[0] == 'parent':
- names = names[1:]
- choice = []
- kind = optypes[self.opnum]
- for name in names:
- FIELD = getattr(S, name)
- if not isinstance(FIELD, lltype.Ptr):
- if kind == 'n' or getkind(FIELD)[0] == kind:
- choice.append(name)
- if not choice:
- raise test_random.CannotProduceOperation
- name = r.choice(choice)
- descr = builder.cpu.fielddescrof(S, name)
- descr._random_info = 'cpu.fielddescrof(..., %r)' % (name,)
- descr._random_type = S
- TYPE = getattr(S, name)
- return v, descr, TYPE
- def produce_into(self, builder, r):
- while True:
- try:
- v, descr, _ = self.field_descr(builder, r)
- self.put(builder, [v], descr)
- except lltype.UninitializedMemoryAccess:
- continue
- break
- class GetInteriorFieldOperation(test_random.AbstractOperation):
- def field_descr(self, builder, r):
- v, A = builder.get_structptr_var(r, type=lltype.Array,
- array_of_structs=True)
- array = getref(lltype.Ptr(A), v)
- v_index = builder.get_index(len(array), r)
- choice = []
- for name in A.OF._names:
- FIELD = getattr(A.OF, name)
- if not isinstance(FIELD, lltype.Ptr):
- choice.append(name)
- if not choice:
- raise test_random.CannotProduceOperation
- name = r.choice(choice)
- descr = builder.cpu.interiorfielddescrof(A, name)
- descr._random_info = 'cpu.interiorfielddescrof(..., %r)' % (name,)
- descr._random_type = A
- TYPE = getattr(A.OF, name)
- return v, v_index, descr, TYPE
- def produce_into(self, builder, r):
- while True:
- try:
- v, v_index, descr, _ = self.field_descr(builder, r)
- self.put(builder, [v, v_index], descr)
- except lltype.UninitializedMemoryAccess:
- continue
- break
- class SetFieldOperation(GetFieldOperation):
- def produce_into(self, builder, r):
- v, descr, TYPE = self.field_descr(builder, r)
- while True:
- if r.random() < 0.3:
- w = ConstInt(r.random_integer())
- else:
- w = r.choice(builder.intvars)
- value = getint(w)
- if rffi.cast(lltype.Signed, rffi.cast(TYPE, value)) == value:
- break
- builder.do(self.opnum, [v, w], descr)
- class SetInteriorFieldOperation(GetInteriorFieldOperation):
- def produce_into(self, builder, r):
- v, v_index, descr, TYPE = self.field_descr(builder, r)
- while True:
- if r.random() < 0.3:
- w = ConstInt(r.random_integer())
- else:
- w = r.choice(builder.intvars)
- value = getint(w)
- if rffi.cast(lltype.Signed, rffi.cast(TYPE, value)) == value:
- break
- builder.do(self.opnum, [v, v_index, w], descr)
- class NewOperation(test_random.AbstractOperation):
- def size_descr(self, builder, S, *vtable):
- descr = builder.cpu.sizeof(S, *vtable)
- descr._random_info = 'cpu.sizeof(...)'
- descr._random_type = S
- return descr
- def produce_into(self, builder, r):
- if self.opnum == rop.NEW_WITH_VTABLE:
- S, vtable = builder.get_random_structure_type_and_vtable(r)
- descr = self.size_descr(builder, S, vtable)
- else:
- S = builder.get_random_structure_type(r)
- descr = self.size_descr(builder, S)
- v_ptr = builder.do(self.opnum, [], descr)
- builder.ptrvars.append((v_ptr, S))
- class ArrayOperation(test_random.AbstractOperation):
- def array_descr(self, builder, A):
- descr = builder.cpu.arraydescrof(A)
- descr._random_info = 'cpu.arraydescrof(...)'
- descr._random_type = A
- return descr
- class GetArrayItemOperation(ArrayOperation):
- def field_descr(self, builder, r):
- v, A = builder.get_arrayptr_var(r)
- array = getref(lltype.Ptr(A), v)
- v_index = builder.get_index(len(array), r)
- descr = self.array_descr(builder, A)
- return v, A, v_index, descr
- def produce_into(self, builder, r):
- while True:
- try:
- v, _, v_index, descr = self.field_descr(builder, r)
- self.put(builder, [v, v_index], descr)
- except lltype.UninitializedMemoryAccess:
- continue
- break
- class SetArrayItemOperation(GetArrayItemOperation):
- def produce_into(self, builder, r):
- v, A, v_index, descr = self.field_descr(builder, r)
- while True:
- if r.random() < 0.3:
- w = ConstInt(r.random_integer())
- else:
- w = r.choice(builder.intvars)
- value = getint(w)
- if rffi.cast(lltype.Signed, rffi.cast(A.OF, value)) == value:
- break
- builder.do(self.opnum, [v, v_index, w], descr)
- class NewArrayOperation(ArrayOperation):
- def produce_into(self, builder, r):
- A = builder.get_random_array_type(r, can_be_array_of_struct=True)
- v_size = builder.get_index(300, r)
- v_ptr = builder.do(self.opnum, [v_size], self.array_descr(builder, A))
- builder.ptrvars.append((v_ptr, A))
- class ArrayLenOperation(ArrayOperation):
- def produce_into(self, builder, r):
- v, A = builder.get_arrayptr_var(r)
- descr = self.array_descr(builder, A)
- self.put(builder, [v], descr)
- class _UnicodeOperation:
- builder_cache = "runicodes"
- struct = rstr.UNICODE
- ptr = lltype.Ptr(struct)
- alloc = staticmethod(rstr.mallocunicode)
- # XXX This should really be runicode.MAXUNICODE, but then
- # lltype.cast_primitive complains.
- max = py.std.sys.maxunicode
- primitive = lltype.UniChar
- set_char = rop.UNICODESETITEM
- class _StrOperation:
- builder_cache = "rstrs"
- struct = rstr.STR
- ptr = lltype.Ptr(struct)
- alloc = staticmethod(rstr.mallocstr)
- max = 255
- primitive = lltype.Char
- set_char = rop.STRSETITEM
- class NewSeqOperation(test_random.AbstractOperation):
- def produce_into(self, builder, r):
- v_length = builder.get_index(10, r)
- v_ptr = builder.do(self.opnum, [v_length])
- getattr(builder, self.builder_cache).append(v_ptr)
- # Initialize the string. Is there a better way to do this?
- for i in range(getint(v_length)):
- v_index = ConstInt(i)
- v_char = ConstInt(r.random_integer() % self.max)
- builder.do(self.set_char, [v_ptr, v_index, v_char])
- class NewStrOperation(NewSeqOperation, _StrOperation):
- pass
- class NewUnicodeOperation(NewSeqOperation, _UnicodeOperation):
- pass
- class AbstractStringOperation(test_random.AbstractOperation):
- def get_string(self, builder, r):
- current = getattr(builder, self.builder_cache)
- if current and r.random() < .8:
- v_string = r.choice(current)
- string = getref(self.ptr, v_string)
- else:
- string = self.alloc(getint(builder.get_index(500, r)))
- v_string = ConstPtr(lltype.cast_opaque_ptr(llmemory.GCREF, string))
- current.append(v_string)
- for i in range(len(string.chars)):
- char = r.random_integer() % self.max
- string.chars[i] = lltype.cast_primitive(self.primitive, char)
- return v_string
- class AbstractGetItemOperation(AbstractStringOperation):
- def produce_into(self, builder, r):
- v_string = self.get_string(builder, r)
- v_index = builder.get_index(len(getref(self.ptr, v_string).chars), r)
- builder.do(self.opnum, [v_string, v_index])
- class AbstractSetItemOperation(AbstractStringOperation):
- def produce_into(self, builder, r):
- v_string = self.get_string(builder, r)
- if isinstance(v_string, ConstPtr):
- raise test_random.CannotProduceOperation # setitem(Const, ...)
- v_index = builder.get_index(len(getref(self.ptr, v_string).chars), r)
- v_target = ConstInt(r.random_integer() % self.max)
- builder.do(self.opnum, [v_string, v_index, v_target])
- class AbstractStringLenOperation(AbstractStringOperation):
- def produce_into(self, builder, r):
- v_string = self.get_string(builder, r)
- builder.do(self.opnum, [v_string])
- class AbstractCopyContentOperation(AbstractStringOperation):
- def produce_into(self, builder, r):
- v_srcstring = self.get_string(builder, r)
- v_dststring = self.get_string(builder, r)
- src = getref(self.ptr, v_srcstring)
- dst = getref(self.ptr, v_dststring)
- if src == dst: # because it's not a
- raise test_random.CannotProduceOperation # memmove(), but memcpy()
- srclen = len(src.chars)
- dstlen = len(dst.chars)
- v_length = builder.get_index(min(srclen, dstlen), r)
- v_srcstart = builder.get_index(srclen - getint(v_length) + 1, r)
- v_dststart = builder.get_index(dstlen - getint(v_length) + 1, r)
- builder.do(self.opnum, [v_srcstring, v_dststring,
- v_srcstart, v_dststart, v_length])
- class StrGetItemOperation(AbstractGetItemOperation, _StrOperation):
- pass
- class UnicodeGetItemOperation(AbstractGetItemOperation, _UnicodeOperation):
- pass
- class StrSetItemOperation(AbstractSetItemOperation, _StrOperation):
- pass
- class UnicodeSetItemOperation(AbstractSetItemOperation, _UnicodeOperation):
- pass
- class StrLenOperation(AbstractStringLenOperation, _StrOperation):
- pass
- class UnicodeLenOperation(AbstractStringLenOperation, _UnicodeOperation):
- pass
- class CopyStrContentOperation(AbstractCopyContentOperation, _StrOperation):
- pass
- class CopyUnicodeContentOperation(AbstractCopyContentOperation,
- _UnicodeOperation):
- pass
- # there are five options in total:
- # 1. non raising call and guard_no_exception
- # 2. raising call and guard_exception
- # 3. raising call and wrong guard_exception
- # 4. raising call and guard_no_exception
- # 5. non raising call and guard_exception
- # (6. test of a cond_call, always non-raising and guard_no_exception)
- class BaseCallOperation(test_random.AbstractOperation):
- def non_raising_func_code(self, builder, r):
- subset = builder.subset_of_intvars(r)
- funcargs = ", ".join(['arg_%d' % i for i in range(len(subset))])
- sum = "intmask(%s)" % " + ".join(
- ['arg_%d' % i for i in range(len(subset))] + ['42'])
- if self.opnum == rop.CALL_I:
- result = 'sum'
- elif self.opnum == rop.CALL_F:
- result = 'float(sum)'
- elif self.opnum == rop.CALL_N:
- result = ''
- else:
- raise AssertionError(self.opnum)
- code = py.code.Source("""
- def f(%s):
- sum = %s
- return %s
- """ % (funcargs, sum, result)).compile()
- d = {'intmask' : intmask}
- exec code in d
- return subset, d['f']
- def raising_func_code(self, builder, r):
- subset = builder.subset_of_intvars(r)
- funcargs = ", ".join(['arg_%d' % i for i in range(len(subset))])
- S, v = builder.get_structptr_var(r, must_have_vtable=True)
- code = py.code.Source("""
- def f(%s):
- raise LLException(vtable, ptr)
- """ % funcargs).compile()
- vtableptr = v._hints['vtable']._as_ptr()
- d = {
- 'ptr': getref_base(S),
- 'vtable' : vtableptr,
- 'LLException' : LLException,
- }
- exec code in d
- return subset, d['f'], vtableptr
- def getresulttype(self):
- if self.opnum == rop.CALL_I:
- return lltype.Signed
- elif self.opnum == rop.CALL_F:
- return lltype.Float
- elif self.opnum == rop.CALL_N or self.opnum == rop.COND_CALL:
- return lltype.Void
- else:
- raise AssertionError(self.opnum)
- def getcalldescr(self, builder, TP):
- assert TP.RESULT == self.getresulttype()
- ef = EffectInfo.MOST_GENERAL
- return builder.cpu.calldescrof(TP, TP.ARGS, TP.RESULT, ef)
- # 1. non raising call and guard_no_exception
- class CallOperation(BaseCallOperation):
- def produce_into(self, builder, r):
- fail_subset = builder.subset_of_intvars(r)
- subset, f = self.non_raising_func_code(builder, r)
- RES = self.getresulttype()
- TP = lltype.FuncType([lltype.Signed] * len(subset), RES)
- ptr = llhelper(lltype.Ptr(TP), f)
- c_addr = ConstAddr(llmemory.cast_ptr_to_adr(ptr), builder.cpu)
- args = [c_addr] + subset
- descr = self.getcalldescr(builder, TP)
- self.put(builder, args, descr)
- op = ResOperation(rop.GUARD_NO_EXCEPTION, [],
- descr=builder.getfaildescr())
- op.setfailargs(fail_subset)
- builder.loop.operations.append(op)
- # 5. Non raising-call and GUARD_EXCEPTION
- class CallOperationException(BaseCallOperation):
- def produce_into(self, builder, r):
- subset, f = self.non_raising_func_code(builder, r)
- RES = self.getresulttype()
- TP = lltype.FuncType([lltype.Signed] * len(subset), RES)
- ptr = llhelper(lltype.Ptr(TP), f)
- c_addr = ConstAddr(llmemory.cast_ptr_to_adr(ptr), builder.cpu)
- args = [c_addr] + subset
- descr = self.getcalldescr(builder, TP)
- self.put(builder, args, descr)
- _, vtableptr = builder.get_random_structure_type_and_vtable(r)
- exc_box = ConstAddr(llmemory.cast_ptr_to_adr(vtableptr), builder.cpu)
- op = ResOperation(rop.GUARD_EXCEPTION, [exc_box],
- descr=builder.getfaildescr())
- op.setfailargs(builder.subset_of_intvars(r))
- op._exc_box = None
- builder.should_fail_by = op
- builder.guard_op = op
- builder.loop.operations.append(op)
- # 2. raising call and guard_exception
- class RaisingCallOperation(BaseCallOperation):
- def produce_into(self, builder, r):
- fail_subset = builder.subset_of_intvars(r)
- subset, f, exc = self.raising_func_code(builder, r)
- TP = lltype.FuncType([lltype.Signed] * len(subset), lltype.Void)
- ptr = llhelper(lltype.Ptr(TP), f)
- c_addr = ConstAddr(llmemory.cast_ptr_to_adr(ptr), builder.cpu)
- args = [c_addr] + subset
- descr = self.getcalldescr(builder, TP)
- self.put(builder, args, descr)
- exc_box = ConstAddr(llmemory.cast_ptr_to_adr(exc), builder.cpu)
- op = ResOperation(rop.GUARD_EXCEPTION, [exc_box],
- descr=builder.getfaildescr())
- op.setfailargs(fail_subset)
- builder.loop.operations.append(op)
- # 4. raising call and guard_no_exception
- class RaisingCallOperationGuardNoException(BaseCallOperation):
- def produce_into(self, builder, r):
- subset, f, exc = self.raising_func_code(builder, r)
- TP = lltype.FuncType([lltype.Signed] * len(subset), lltype.Void)
- ptr = llhelper(lltype.Ptr(TP), f)
- c_addr = ConstAddr(llmemory.cast_ptr_to_adr(ptr), builder.cpu)
- args = [c_addr] + subset
- descr = self.getcalldescr(builder, TP)
- self.put(builder, args, descr)
- op = ResOperation(rop.GUARD_NO_EXCEPTION, [],
- descr=builder.getfaildescr())
- op._exc_box = ConstAddr(llmemory.cast_ptr_to_adr(exc), builder.cpu)
- op.setfailargs(builder.subset_of_intvars(r))
- builder.should_fail_by = op
- builder.guard_op = op
- builder.loop.operations.append(op)
- # 3. raising call and wrong guard_exception
- class RaisingCallOperationWrongGuardException(BaseCallOperation):
- def produce_into(self, builder, r):
- subset, f, exc = self.raising_func_code(builder, r)
- TP = lltype.FuncType([lltype.Signed] * len(subset), lltype.Void)
- ptr = llhelper(lltype.Ptr(TP), f)
- c_addr = ConstAddr(llmemory.cast_ptr_to_adr(ptr), builder.cpu)
- args = [c_addr] + subset
- descr = self.getcalldescr(builder, TP)
- self.put(builder, args, descr)
- while True:
- _, vtableptr = builder.get_random_structure_type_and_vtable(r)
- if vtableptr != exc:
- break
- other_box = ConstAddr(llmemory.cast_ptr_to_adr(vtableptr), builder.cpu)
- op = ResOperation(rop.GUARD_EXCEPTION, [other_box],
- descr=builder.getfaildescr())
- op._exc_box = ConstAddr(llmemory.cast_ptr_to_adr(exc), builder.cpu)
- op.setfailargs(builder.subset_of_intvars(r))
- builder.should_fail_by = op
- builder.guard_op = op
- builder.loop.operations.append(op)
- # 6. a conditional call (for now always with no exception raised)
- class CondCallOperation(BaseCallOperation):
- def produce_into(self, builder, r):
- fail_subset = builder.subset_of_intvars(r)
- v_cond = builder.get_bool_var(r)
- subset = builder.subset_of_intvars(r)[:4]
- for i in range(len(subset)):
- if r.random() < 0.35:
- subset[i] = ConstInt(r.random_integer())
- #
- seen = []
- def call_me(*args):
- if len(seen) == 0:
- seen.append(args)
- else:
- assert seen[0] == args
- #
- TP = lltype.FuncType([lltype.Signed] * len(subset), lltype.Void)
- ptr = llhelper(lltype.Ptr(TP), call_me)
- c_addr = ConstAddr(llmemory.cast_ptr_to_adr(ptr), builder.cpu)
- args = [v_cond, c_addr] + subset
- descr = self.getcalldescr(builder, TP)
- self.put(builder, args, descr)
- op = ResOperation(rop.GUARD_NO_EXCEPTION, [],
- descr=builder.getfaildescr())
- op.setfailargs(fail_subset)
- builder.loop.operations.append(op)
- # ____________________________________________________________
- OPERATIONS = test_random.OPERATIONS[:]
- for i in range(4): # make more common
- OPERATIONS.append(GetFieldOperation(rop.GETFIELD_GC_I))
- OPERATIONS.append(GetFieldOperation(rop.GETFIELD_GC_I))
- OPERATIONS.append(GetInteriorFieldOperation(rop.GETINTERIORFIELD_GC_I))
- OPERATIONS.append(GetInteriorFieldOperation(rop.GETINTERIORFIELD_GC_I))
- OPERATIONS.append(SetFieldOperation(rop.SETFIELD_GC))
- OPERATIONS.append(SetInteriorFieldOperation(rop.SETINTERIORFIELD_GC))
- OPERATIONS.append(NewOperation(rop.NEW))
- OPERATIONS.append(NewOperation(rop.NEW_WITH_VTABLE))
- OPERATIONS.append(GetArrayItemOperation(rop.GETARRAYITEM_GC_I))
- OPERATIONS.append(GetArrayItemOperation(rop.GETARRAYITEM_GC_I))
- OPERATIONS.append(SetArrayItemOperation(rop.SETARRAYITEM_GC))
- OPERATIONS.append(NewArrayOperation(rop.NEW_ARRAY_CLEAR))
- OPERATIONS.append(ArrayLenOperation(rop.ARRAYLEN_GC))
- OPERATIONS.append(NewStrOperation(rop.NEWSTR))
- OPERATIONS.append(NewUnicodeOperation(rop.NEWUNICODE))
- OPERATIONS.append(StrGetItemOperation(rop.STRGETITEM))
- OPERATIONS.append(UnicodeGetItemOperation(rop.UNICODEGETITEM))
- OPERATIONS.append(StrSetItemOperation(rop.STRSETITEM))
- OPERATIONS.append(UnicodeSetItemOperation(rop.UNICODESETITEM))
- OPERATIONS.append(StrLenOperation(rop.STRLEN))
- OPERATIONS.append(UnicodeLenOperation(rop.UNICODELEN))
- OPERATIONS.append(CopyStrContentOperation(rop.COPYSTRCONTENT))
- OPERATIONS.append(CopyUnicodeContentOperation(rop.COPYUNICODECONTENT))
- for i in range(2):
- OPERATIONS.append(GuardClassOperation(rop.GUARD_CLASS))
- OPERATIONS.append(CondCallOperation(rop.COND_CALL))
- OPERATIONS.append(RaisingCallOperation(rop.CALL_N))
- OPERATIONS.append(RaisingCallOperationGuardNoException(rop.CALL_N))
- OPERATIONS.append(RaisingCallOperationWrongGuardException(rop.CALL_N))
- OPERATIONS.append(GuardNonNullClassOperation(rop.GUARD_NONNULL_CLASS))
- for _opnum in [rop.CALL_I, rop.CALL_F, rop.CALL_N]:
- OPERATIONS.append(CallOperation(_opnum))
- OPERATIONS.append(CallOperationException(_opnum))
- LLtypeOperationBuilder.OPERATIONS = OPERATIONS
- # ____________________________________________________________
- def test_ll_random_function():
- test_random.test_random_function(LLtypeOperationBuilder)