/pypy/jit/backend/test/runner_test.py
Python | 3299 lines | 3048 code | 145 blank | 106 comment | 194 complexity | 6a2f55e39c425e24ba25e3c9b6b599bb MD5 | raw file
Large files files are truncated, but you can click here to view the full file
- import py, sys, random, os, struct, operator
- from pypy.jit.metainterp.history import (AbstractFailDescr,
- AbstractDescr,
- BasicFailDescr,
- BoxInt, Box, BoxPtr,
- JitCellToken, TargetToken,
- ConstInt, ConstPtr,
- BoxObj,
- ConstObj, BoxFloat, ConstFloat)
- from pypy.jit.metainterp.resoperation import ResOperation, rop
- from pypy.jit.metainterp.typesystem import deref
- from pypy.jit.codewriter.effectinfo import EffectInfo
- from pypy.jit.tool.oparser import parse
- from pypy.rpython.lltypesystem import lltype, llmemory, rstr, rffi, rclass
- from pypy.rpython.ootypesystem import ootype
- from pypy.rpython.annlowlevel import llhelper
- from pypy.rpython.llinterp import LLException
- from pypy.jit.codewriter import heaptracker, longlong
- from pypy.rlib import longlong2float
- from pypy.rlib.rarithmetic import intmask, is_valid_int
- from pypy.jit.backend.detect_cpu import autodetect_main_model_and_size
- def boxfloat(x):
- return BoxFloat(longlong.getfloatstorage(x))
- def constfloat(x):
- return ConstFloat(longlong.getfloatstorage(x))
- def boxlonglong(ll):
- if longlong.is_64_bit:
- return BoxInt(ll)
- else:
- return BoxFloat(ll)
- class Runner(object):
- add_loop_instruction = ['overload for a specific cpu']
- bridge_loop_instruction = ['overload for a specific cpu']
- def execute_operation(self, opname, valueboxes, result_type, descr=None):
- inputargs, operations = self._get_single_operation_list(opname,
- result_type,
- valueboxes,
- descr)
- looptoken = JitCellToken()
- self.cpu.compile_loop(inputargs, operations, looptoken)
- args = []
- for box in inputargs:
- if isinstance(box, BoxInt):
- args.append(box.getint())
- elif isinstance(box, (BoxPtr, BoxObj)):
- args.append(box.getref_base())
- elif isinstance(box, BoxFloat):
- args.append(box.getfloatstorage())
- else:
- raise NotImplementedError(box)
- res = self.cpu.execute_token(looptoken, *args)
- if res is operations[-1].getdescr():
- self.guard_failed = False
- else:
- self.guard_failed = True
- if result_type == 'int':
- return BoxInt(self.cpu.get_latest_value_int(0))
- elif result_type == 'ref':
- return BoxPtr(self.cpu.get_latest_value_ref(0))
- elif result_type == 'float':
- return BoxFloat(self.cpu.get_latest_value_float(0))
- elif result_type == 'void':
- return None
- else:
- assert False
- def _get_single_operation_list(self, opnum, result_type, valueboxes,
- descr):
- if result_type == 'void':
- result = None
- elif result_type == 'int':
- result = BoxInt()
- elif result_type == 'ref':
- result = BoxPtr()
- elif result_type == 'float':
- result = BoxFloat()
- else:
- raise ValueError(result_type)
- if result is None:
- results = []
- else:
- results = [result]
- operations = [ResOperation(opnum, valueboxes, result),
- ResOperation(rop.FINISH, results, None,
- descr=BasicFailDescr(0))]
- if operations[0].is_guard():
- operations[0].setfailargs([])
- if not descr:
- descr = BasicFailDescr(1)
- if descr is not None:
- operations[0].setdescr(descr)
- inputargs = []
- for box in valueboxes:
- if isinstance(box, Box) and box not in inputargs:
- inputargs.append(box)
- return inputargs, operations
- class BaseBackendTest(Runner):
- avoid_instances = False
- def test_compile_linear_loop(self):
- i0 = BoxInt()
- i1 = BoxInt()
- operations = [
- ResOperation(rop.INT_ADD, [i0, ConstInt(1)], i1),
- ResOperation(rop.FINISH, [i1], None, descr=BasicFailDescr(1))
- ]
- inputargs = [i0]
- looptoken = JitCellToken()
- self.cpu.compile_loop(inputargs, operations, looptoken)
- fail = self.cpu.execute_token(looptoken, 2)
- res = self.cpu.get_latest_value_int(0)
- assert res == 3
- assert fail.identifier == 1
- def test_compile_loop(self):
- i0 = BoxInt()
- i1 = BoxInt()
- i2 = BoxInt()
- looptoken = JitCellToken()
- targettoken = TargetToken()
- operations = [
- ResOperation(rop.LABEL, [i0], None, descr=targettoken),
- ResOperation(rop.INT_ADD, [i0, ConstInt(1)], i1),
- ResOperation(rop.INT_LE, [i1, ConstInt(9)], i2),
- ResOperation(rop.GUARD_TRUE, [i2], None, descr=BasicFailDescr(2)),
- ResOperation(rop.JUMP, [i1], None, descr=targettoken),
- ]
- inputargs = [i0]
- operations[3].setfailargs([i1])
- self.cpu.compile_loop(inputargs, operations, looptoken)
- fail = self.cpu.execute_token(looptoken, 2)
- assert fail.identifier == 2
- res = self.cpu.get_latest_value_int(0)
- assert res == 10
- def test_compile_with_holes_in_fail_args(self):
- i0 = BoxInt()
- i1 = BoxInt()
- i2 = BoxInt()
- i3 = BoxInt()
- looptoken = JitCellToken()
- targettoken = TargetToken()
- operations = [
- ResOperation(rop.INT_SUB, [i3, ConstInt(42)], i0),
- ResOperation(rop.LABEL, [i0], None, descr=targettoken),
- ResOperation(rop.INT_ADD, [i0, ConstInt(1)], i1),
- ResOperation(rop.INT_LE, [i1, ConstInt(9)], i2),
- ResOperation(rop.GUARD_TRUE, [i2], None, descr=BasicFailDescr(2)),
- ResOperation(rop.JUMP, [i1], None, descr=targettoken),
- ]
- inputargs = [i3]
- operations[4].setfailargs([None, None, i1, None])
- self.cpu.compile_loop(inputargs, operations, looptoken)
- fail = self.cpu.execute_token(looptoken, 44)
- assert fail.identifier == 2
- res = self.cpu.get_latest_value_int(2)
- assert res == 10
- def test_backends_dont_keep_loops_alive(self):
- import weakref, gc
- self.cpu.dont_keepalive_stuff = True
- i0 = BoxInt()
- i1 = BoxInt()
- i2 = BoxInt()
- looptoken = JitCellToken()
- targettoken = TargetToken()
- operations = [
- ResOperation(rop.LABEL, [i0], None, descr=targettoken),
- ResOperation(rop.INT_ADD, [i0, ConstInt(1)], i1),
- ResOperation(rop.INT_LE, [i1, ConstInt(9)], i2),
- ResOperation(rop.GUARD_TRUE, [i2], None, descr=BasicFailDescr()),
- ResOperation(rop.JUMP, [i1], None, descr=targettoken),
- ]
- inputargs = [i0]
- operations[3].setfailargs([i1])
- wr_i1 = weakref.ref(i1)
- wr_guard = weakref.ref(operations[2])
- self.cpu.compile_loop(inputargs, operations, looptoken)
- if hasattr(looptoken, '_x86_ops_offset'):
- del looptoken._x86_ops_offset # else it's kept alive
- del i0, i1, i2
- del inputargs
- del operations
- gc.collect()
- assert not wr_i1() and not wr_guard()
- def test_compile_bridge(self):
- self.cpu.total_compiled_loops = 0
- self.cpu.total_compiled_bridges = 0
- i0 = BoxInt()
- i1 = BoxInt()
- i2 = BoxInt()
- faildescr1 = BasicFailDescr(1)
- faildescr2 = BasicFailDescr(2)
- looptoken = JitCellToken()
- targettoken = TargetToken()
- operations = [
- ResOperation(rop.LABEL, [i0], None, descr=targettoken),
- ResOperation(rop.INT_ADD, [i0, ConstInt(1)], i1),
- ResOperation(rop.INT_LE, [i1, ConstInt(9)], i2),
- ResOperation(rop.GUARD_TRUE, [i2], None, descr=faildescr1),
- ResOperation(rop.JUMP, [i1], None, descr=targettoken),
- ]
- inputargs = [i0]
- operations[3].setfailargs([i1])
- self.cpu.compile_loop(inputargs, operations, looptoken)
- i1b = BoxInt()
- i3 = BoxInt()
- bridge = [
- ResOperation(rop.INT_LE, [i1b, ConstInt(19)], i3),
- ResOperation(rop.GUARD_TRUE, [i3], None, descr=faildescr2),
- ResOperation(rop.JUMP, [i1b], None, descr=targettoken),
- ]
- bridge[1].setfailargs([i1b])
- self.cpu.compile_bridge(faildescr1, [i1b], bridge, looptoken)
- fail = self.cpu.execute_token(looptoken, 2)
- assert fail.identifier == 2
- res = self.cpu.get_latest_value_int(0)
- assert res == 20
- assert self.cpu.total_compiled_loops == 1
- assert self.cpu.total_compiled_bridges == 1
- return looptoken
- def test_compile_bridge_with_holes(self):
- i0 = BoxInt()
- i1 = BoxInt()
- i2 = BoxInt()
- i3 = BoxInt()
- faildescr1 = BasicFailDescr(1)
- faildescr2 = BasicFailDescr(2)
- looptoken = JitCellToken()
- targettoken = TargetToken()
- operations = [
- ResOperation(rop.INT_SUB, [i3, ConstInt(42)], i0),
- ResOperation(rop.LABEL, [i0], None, descr=targettoken),
- ResOperation(rop.INT_ADD, [i0, ConstInt(1)], i1),
- ResOperation(rop.INT_LE, [i1, ConstInt(9)], i2),
- ResOperation(rop.GUARD_TRUE, [i2], None, descr=faildescr1),
- ResOperation(rop.JUMP, [i1], None, descr=targettoken),
- ]
- inputargs = [i3]
- operations[4].setfailargs([None, i1, None])
- self.cpu.compile_loop(inputargs, operations, looptoken)
- i1b = BoxInt()
- i3 = BoxInt()
- bridge = [
- ResOperation(rop.INT_LE, [i1b, ConstInt(19)], i3),
- ResOperation(rop.GUARD_TRUE, [i3], None, descr=faildescr2),
- ResOperation(rop.JUMP, [i1b], None, descr=targettoken),
- ]
- bridge[1].setfailargs([i1b])
- self.cpu.compile_bridge(faildescr1, [i1b], bridge, looptoken)
- fail = self.cpu.execute_token(looptoken, 2)
- assert fail.identifier == 2
- res = self.cpu.get_latest_value_int(0)
- assert res == 20
- def test_compile_big_bridge_out_of_small_loop(self):
- i0 = BoxInt()
- faildescr1 = BasicFailDescr(1)
- looptoken = JitCellToken()
- operations = [
- ResOperation(rop.GUARD_FALSE, [i0], None, descr=faildescr1),
- ResOperation(rop.FINISH, [], None, descr=BasicFailDescr(2)),
- ]
- inputargs = [i0]
- operations[0].setfailargs([i0])
- self.cpu.compile_loop(inputargs, operations, looptoken)
- i1list = [BoxInt() for i in range(1000)]
- bridge = []
- iprev = i0
- for i1 in i1list:
- bridge.append(ResOperation(rop.INT_ADD, [iprev, ConstInt(1)], i1))
- iprev = i1
- bridge.append(ResOperation(rop.GUARD_FALSE, [i0], None,
- descr=BasicFailDescr(3)))
- bridge.append(ResOperation(rop.FINISH, [], None,
- descr=BasicFailDescr(4)))
- bridge[-2].setfailargs(i1list)
- self.cpu.compile_bridge(faildescr1, [i0], bridge, looptoken)
- fail = self.cpu.execute_token(looptoken, 1)
- assert fail.identifier == 3
- for i in range(1000):
- res = self.cpu.get_latest_value_int(i)
- assert res == 2 + i
- def test_get_latest_value_count(self):
- i0 = BoxInt()
- i1 = BoxInt()
- i2 = BoxInt()
- faildescr1 = BasicFailDescr(1)
- looptoken = JitCellToken()
- targettoken = TargetToken()
- operations = [
- ResOperation(rop.LABEL, [i0], None, descr=targettoken),
- ResOperation(rop.INT_ADD, [i0, ConstInt(1)], i1),
- ResOperation(rop.INT_LE, [i1, ConstInt(9)], i2),
- ResOperation(rop.GUARD_TRUE, [i2], None, descr=faildescr1),
- ResOperation(rop.JUMP, [i1], None, descr=targettoken),
- ]
- inputargs = [i0]
- operations[3].setfailargs([None, i1, None])
- self.cpu.compile_loop(inputargs, operations, looptoken)
- fail = self.cpu.execute_token(looptoken, 2)
- assert fail is faildescr1
- count = self.cpu.get_latest_value_count()
- assert count == 3
- assert self.cpu.get_latest_value_int(1) == 10
- assert self.cpu.get_latest_value_int(1) == 10 # multiple reads ok
- self.cpu.clear_latest_values(3)
- def test_finish(self):
- i0 = BoxInt()
- class UntouchableFailDescr(AbstractFailDescr):
- def __setattr__(self, name, value):
- if name == 'index':
- return AbstractFailDescr.__setattr__(self, name, value)
- py.test.fail("finish descrs should not be touched")
- faildescr = UntouchableFailDescr() # to check that is not touched
- looptoken = JitCellToken()
- operations = [
- ResOperation(rop.FINISH, [i0], None, descr=faildescr)
- ]
- self.cpu.compile_loop([i0], operations, looptoken)
- fail = self.cpu.execute_token(looptoken, 99)
- assert fail is faildescr
- res = self.cpu.get_latest_value_int(0)
- assert res == 99
- looptoken = JitCellToken()
- operations = [
- ResOperation(rop.FINISH, [ConstInt(42)], None, descr=faildescr)
- ]
- self.cpu.compile_loop([], operations, looptoken)
- fail = self.cpu.execute_token(looptoken)
- assert fail is faildescr
- res = self.cpu.get_latest_value_int(0)
- assert res == 42
- looptoken = JitCellToken()
- operations = [
- ResOperation(rop.FINISH, [], None, descr=faildescr)
- ]
- self.cpu.compile_loop([], operations, looptoken)
- fail = self.cpu.execute_token(looptoken)
- assert fail is faildescr
- if self.cpu.supports_floats:
- looptoken = JitCellToken()
- f0 = BoxFloat()
- operations = [
- ResOperation(rop.FINISH, [f0], None, descr=faildescr)
- ]
- self.cpu.compile_loop([f0], operations, looptoken)
- value = longlong.getfloatstorage(-61.25)
- fail = self.cpu.execute_token(looptoken, value)
- assert fail is faildescr
- res = self.cpu.get_latest_value_float(0)
- assert longlong.getrealfloat(res) == -61.25
- looptoken = JitCellToken()
- operations = [
- ResOperation(rop.FINISH, [constfloat(42.5)], None, descr=faildescr)
- ]
- self.cpu.compile_loop([], operations, looptoken)
- fail = self.cpu.execute_token(looptoken)
- assert fail is faildescr
- res = self.cpu.get_latest_value_float(0)
- assert longlong.getrealfloat(res) == 42.5
- def test_execute_operations_in_env(self):
- cpu = self.cpu
- x = BoxInt(123)
- y = BoxInt(456)
- z = BoxInt(579)
- t = BoxInt(455)
- u = BoxInt(0) # False
- looptoken = JitCellToken()
- targettoken = TargetToken()
- operations = [
- ResOperation(rop.LABEL, [y, x], None, descr=targettoken),
- ResOperation(rop.INT_ADD, [x, y], z),
- ResOperation(rop.INT_SUB, [y, ConstInt(1)], t),
- ResOperation(rop.INT_EQ, [t, ConstInt(0)], u),
- ResOperation(rop.GUARD_FALSE, [u], None,
- descr=BasicFailDescr()),
- ResOperation(rop.JUMP, [t, z], None, descr=targettoken),
- ]
- operations[-2].setfailargs([t, z])
- cpu.compile_loop([x, y], operations, looptoken)
- res = self.cpu.execute_token(looptoken, 0, 10)
- assert self.cpu.get_latest_value_int(0) == 0
- assert self.cpu.get_latest_value_int(1) == 55
- def test_int_operations(self):
- from pypy.jit.metainterp.test.test_executor import get_int_tests
- for opnum, boxargs, retvalue in get_int_tests():
- res = self.execute_operation(opnum, boxargs, 'int')
- assert res.value == retvalue
- def test_float_operations(self):
- from pypy.jit.metainterp.test.test_executor import get_float_tests
- for opnum, boxargs, rettype, retvalue in get_float_tests(self.cpu):
- res = self.execute_operation(opnum, boxargs, rettype)
- if isinstance(res, BoxFloat):
- assert res.getfloat() == retvalue
- else:
- assert res.value == retvalue
- def test_ovf_operations(self, reversed=False):
- minint = -sys.maxint-1
- boom = 'boom'
- for opnum, testcases in [
- (rop.INT_ADD_OVF, [(10, -2, 8),
- (-1, minint, boom),
- (sys.maxint//2, sys.maxint//2+2, boom)]),
- (rop.INT_SUB_OVF, [(-20, -23, 3),
- (-2, sys.maxint, boom),
- (sys.maxint//2, -(sys.maxint//2+2), boom)]),
- (rop.INT_MUL_OVF, [(minint/2, 2, minint),
- (-2, -(minint/2), minint),
- (minint/2, -2, boom)]),
- ]:
- v1 = BoxInt(testcases[0][0])
- v2 = BoxInt(testcases[0][1])
- v_res = BoxInt()
- #
- if not reversed:
- ops = [
- ResOperation(opnum, [v1, v2], v_res),
- ResOperation(rop.GUARD_NO_OVERFLOW, [], None,
- descr=BasicFailDescr(1)),
- ResOperation(rop.FINISH, [v_res], None,
- descr=BasicFailDescr(2)),
- ]
- ops[1].setfailargs([])
- else:
- v_exc = self.cpu.ts.BoxRef()
- ops = [
- ResOperation(opnum, [v1, v2], v_res),
- ResOperation(rop.GUARD_OVERFLOW, [], None,
- descr=BasicFailDescr(1)),
- ResOperation(rop.FINISH, [], None, descr=BasicFailDescr(2)),
- ]
- ops[1].setfailargs([v_res])
- #
- looptoken = JitCellToken()
- self.cpu.compile_loop([v1, v2], ops, looptoken)
- for x, y, z in testcases:
- excvalue = self.cpu.grab_exc_value()
- assert not excvalue
- fail = self.cpu.execute_token(looptoken, x, y)
- if (z == boom) ^ reversed:
- assert fail.identifier == 1
- else:
- assert fail.identifier == 2
- if z != boom:
- assert self.cpu.get_latest_value_int(0) == z
- excvalue = self.cpu.grab_exc_value()
- assert not excvalue
- def test_ovf_operations_reversed(self):
- self.test_ovf_operations(reversed=True)
- def test_bh_call(self):
- cpu = self.cpu
- #
- def func(c):
- return chr(ord(c) + 1)
- FPTR = self.Ptr(self.FuncType([lltype.Char], lltype.Char))
- func_ptr = llhelper(FPTR, func)
- calldescr = cpu.calldescrof(deref(FPTR), (lltype.Char,), lltype.Char,
- EffectInfo.MOST_GENERAL)
- x = cpu.bh_call_i(self.get_funcbox(cpu, func_ptr).value,
- calldescr, [ord('A')], None, None)
- assert x == ord('B')
- if cpu.supports_floats:
- def func(f, i):
- assert isinstance(f, float)
- assert is_valid_int(i)
- return f - float(i)
- FPTR = self.Ptr(self.FuncType([lltype.Float, lltype.Signed],
- lltype.Float))
- func_ptr = llhelper(FPTR, func)
- FTP = deref(FPTR)
- calldescr = cpu.calldescrof(FTP, FTP.ARGS, FTP.RESULT,
- EffectInfo.MOST_GENERAL)
- x = cpu.bh_call_f(self.get_funcbox(cpu, func_ptr).value,
- calldescr,
- [42], None, [longlong.getfloatstorage(3.5)])
- assert longlong.getrealfloat(x) == 3.5 - 42
- def test_call(self):
- from pypy.rlib.libffi import types, FUNCFLAG_CDECL
- def func_int(a, b):
- return a + b
- def func_char(c, c1):
- return chr(ord(c) + ord(c1))
- functions = [
- (func_int, lltype.Signed, types.sint, 655360),
- (func_int, rffi.SHORT, types.sint16, 1213),
- (func_char, lltype.Char, types.uchar, 12)
- ]
- for func, TP, ffi_type, num in functions:
- cpu = self.cpu
- #
- FPTR = self.Ptr(self.FuncType([TP, TP], TP))
- func_ptr = llhelper(FPTR, func)
- FUNC = deref(FPTR)
- funcbox = self.get_funcbox(cpu, func_ptr)
- # first, try it with the "normal" calldescr
- calldescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
- EffectInfo.MOST_GENERAL)
- res = self.execute_operation(rop.CALL,
- [funcbox, BoxInt(num), BoxInt(num)],
- 'int', descr=calldescr)
- assert res.value == 2 * num
- # then, try it with the dynamic calldescr
- dyn_calldescr = cpu.calldescrof_dynamic([ffi_type, ffi_type], ffi_type,
- EffectInfo.MOST_GENERAL,
- ffi_flags=FUNCFLAG_CDECL)
- res = self.execute_operation(rop.CALL,
- [funcbox, BoxInt(num), BoxInt(num)],
- 'int', descr=dyn_calldescr)
- assert res.value == 2 * num
- if cpu.supports_floats:
- def func(f0, f1, f2, f3, f4, f5, f6, i0, i1, f7, f8, f9):
- return f0 + f1 + f2 + f3 + f4 + f5 + f6 + float(i0 + i1) + f7 + f8 + f9
- F = lltype.Float
- I = lltype.Signed
- FUNC = self.FuncType([F] * 7 + [I] * 2 + [F] * 3, F)
- FPTR = self.Ptr(FUNC)
- func_ptr = llhelper(FPTR, func)
- calldescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
- EffectInfo.MOST_GENERAL)
- funcbox = self.get_funcbox(cpu, func_ptr)
- args = ([boxfloat(.1) for i in range(7)] +
- [BoxInt(1), BoxInt(2), boxfloat(.2), boxfloat(.3),
- boxfloat(.4)])
- res = self.execute_operation(rop.CALL,
- [funcbox] + args,
- 'float', descr=calldescr)
- assert abs(res.getfloat() - 4.6) < 0.0001
- def test_call_many_arguments(self):
- # Test calling a function with a large number of arguments (more than
- # 6, which will force passing some arguments on the stack on 64-bit)
- def func(*args):
- assert len(args) == 16
- # Try to sum up args in a way that would probably detect a
- # transposed argument
- return sum(arg * (2**i) for i, arg in enumerate(args))
- FUNC = self.FuncType([lltype.Signed]*16, lltype.Signed)
- FPTR = self.Ptr(FUNC)
- calldescr = self.cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
- EffectInfo.MOST_GENERAL)
- func_ptr = llhelper(FPTR, func)
- args = range(16)
- funcbox = self.get_funcbox(self.cpu, func_ptr)
- res = self.execute_operation(rop.CALL, [funcbox] + map(BoxInt, args), 'int', descr=calldescr)
- assert res.value == func(*args)
- def test_call_box_func(self):
- def a(a1, a2):
- return a1 + a2
- def b(b1, b2):
- return b1 * b2
- arg1 = 40
- arg2 = 2
- for f in [a, b]:
- TP = lltype.Signed
- FPTR = self.Ptr(self.FuncType([TP, TP], TP))
- func_ptr = llhelper(FPTR, f)
- FUNC = deref(FPTR)
- funcconst = self.get_funcbox(self.cpu, func_ptr)
- funcbox = funcconst.clonebox()
- calldescr = self.cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
- EffectInfo.MOST_GENERAL)
- res = self.execute_operation(rop.CALL,
- [funcbox, BoxInt(arg1), BoxInt(arg2)],
- 'int', descr=calldescr)
- assert res.getint() == f(arg1, arg2)
- def test_call_stack_alignment(self):
- # test stack alignment issues, notably for Mac OS/X.
- # also test the ordering of the arguments.
- def func_ints(*ints):
- s = str(ints) + '\n'
- os.write(1, s) # don't remove -- crash if the stack is misaligned
- return sum([(10+i)*(5+j) for i, j in enumerate(ints)])
- for nb_args in range(0, 35):
- cpu = self.cpu
- TP = lltype.Signed
- #
- FPTR = self.Ptr(self.FuncType([TP] * nb_args, TP))
- func_ptr = llhelper(FPTR, func_ints)
- FUNC = deref(FPTR)
- calldescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
- EffectInfo.MOST_GENERAL)
- funcbox = self.get_funcbox(cpu, func_ptr)
- args = [280-24*i for i in range(nb_args)]
- res = self.execute_operation(rop.CALL,
- [funcbox] + map(BoxInt, args),
- 'int', descr=calldescr)
- assert res.value == func_ints(*args)
- def test_call_with_const_floats(self):
- def func(f1, f2):
- return f1 + f2
- FUNC = self.FuncType([lltype.Float, lltype.Float], lltype.Float)
- FPTR = self.Ptr(FUNC)
- calldescr = self.cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
- EffectInfo.MOST_GENERAL)
- func_ptr = llhelper(FPTR, func)
- funcbox = self.get_funcbox(self.cpu, func_ptr)
- res = self.execute_operation(rop.CALL, [funcbox, constfloat(1.5),
- constfloat(2.5)], 'float',
- descr=calldescr)
- assert res.getfloat() == 4.0
- def test_field_basic(self):
- t_box, T_box = self.alloc_instance(self.T)
- fielddescr = self.cpu.fielddescrof(self.S, 'value')
- assert not fielddescr.is_pointer_field()
- #
- res = self.execute_operation(rop.SETFIELD_GC, [t_box, BoxInt(39082)],
- 'void', descr=fielddescr)
- assert res is None
- res = self.execute_operation(rop.GETFIELD_GC, [t_box],
- 'int', descr=fielddescr)
- assert res.value == 39082
- #
- fielddescr1 = self.cpu.fielddescrof(self.S, 'chr1')
- fielddescr2 = self.cpu.fielddescrof(self.S, 'chr2')
- shortdescr = self.cpu.fielddescrof(self.S, 'short')
- self.execute_operation(rop.SETFIELD_GC, [t_box, BoxInt(250)],
- 'void', descr=fielddescr2)
- self.execute_operation(rop.SETFIELD_GC, [t_box, BoxInt(133)],
- 'void', descr=fielddescr1)
- self.execute_operation(rop.SETFIELD_GC, [t_box, BoxInt(1331)],
- 'void', descr=shortdescr)
- res = self.execute_operation(rop.GETFIELD_GC, [t_box],
- 'int', descr=fielddescr2)
- assert res.value == 250
- res = self.execute_operation(rop.GETFIELD_GC, [t_box],
- 'int', descr=fielddescr1)
- assert res.value == 133
- res = self.execute_operation(rop.GETFIELD_GC, [t_box],
- 'int', descr=shortdescr)
- assert res.value == 1331
- #
- u_box, U_box = self.alloc_instance(self.U)
- fielddescr2 = self.cpu.fielddescrof(self.S, 'next')
- assert fielddescr2.is_pointer_field()
- res = self.execute_operation(rop.SETFIELD_GC, [t_box, u_box],
- 'void', descr=fielddescr2)
- assert res is None
- res = self.execute_operation(rop.GETFIELD_GC, [t_box],
- 'ref', descr=fielddescr2)
- assert res.value == u_box.value
- #
- null_const = self.null_instance().constbox()
- res = self.execute_operation(rop.SETFIELD_GC, [t_box, null_const],
- 'void', descr=fielddescr2)
- assert res is None
- res = self.execute_operation(rop.GETFIELD_GC, [t_box],
- 'ref', descr=fielddescr2)
- assert res.value == null_const.value
- if self.cpu.supports_floats:
- floatdescr = self.cpu.fielddescrof(self.S, 'float')
- self.execute_operation(rop.SETFIELD_GC, [t_box, boxfloat(3.4)],
- 'void', descr=floatdescr)
- res = self.execute_operation(rop.GETFIELD_GC, [t_box],
- 'float', descr=floatdescr)
- assert res.getfloat() == 3.4
- #
- self.execute_operation(rop.SETFIELD_GC, [t_box, constfloat(-3.6)],
- 'void', descr=floatdescr)
- res = self.execute_operation(rop.GETFIELD_GC, [t_box],
- 'float', descr=floatdescr)
- assert res.getfloat() == -3.6
- def test_passing_guards(self):
- t_box, T_box = self.alloc_instance(self.T)
- nullbox = self.null_instance()
- all = [(rop.GUARD_TRUE, [BoxInt(1)]),
- (rop.GUARD_FALSE, [BoxInt(0)]),
- (rop.GUARD_VALUE, [BoxInt(42), ConstInt(42)]),
- ]
- if not self.avoid_instances:
- all.extend([
- (rop.GUARD_NONNULL, [t_box]),
- (rop.GUARD_ISNULL, [nullbox])
- ])
- if self.cpu.supports_floats:
- all.append((rop.GUARD_VALUE, [boxfloat(3.5), constfloat(3.5)]))
- for (opname, args) in all:
- assert self.execute_operation(opname, args, 'void') == None
- assert not self.guard_failed
- def test_passing_guard_class(self):
- t_box, T_box = self.alloc_instance(self.T)
- #null_box = ConstPtr(lltype.cast_opaque_ptr(llmemory.GCREF, lltype.nullptr(T)))
- self.execute_operation(rop.GUARD_CLASS, [t_box, T_box], 'void')
- assert not self.guard_failed
- self.execute_operation(rop.GUARD_NONNULL_CLASS, [t_box, T_box], 'void')
- assert not self.guard_failed
- def test_failing_guards(self):
- t_box, T_box = self.alloc_instance(self.T)
- nullbox = self.null_instance()
- all = [(rop.GUARD_TRUE, [BoxInt(0)]),
- (rop.GUARD_FALSE, [BoxInt(1)]),
- (rop.GUARD_VALUE, [BoxInt(42), ConstInt(41)]),
- ]
- if not self.avoid_instances:
- all.extend([
- (rop.GUARD_NONNULL, [nullbox]),
- (rop.GUARD_ISNULL, [t_box])])
- if self.cpu.supports_floats:
- all.append((rop.GUARD_VALUE, [boxfloat(-1.0), constfloat(1.0)]))
- for opname, args in all:
- assert self.execute_operation(opname, args, 'void') == None
- assert self.guard_failed
- def test_failing_guard_class(self):
- t_box, T_box = self.alloc_instance(self.T)
- u_box, U_box = self.alloc_instance(self.U)
- null_box = self.null_instance()
- for opname, args in [(rop.GUARD_CLASS, [t_box, U_box]),
- (rop.GUARD_CLASS, [u_box, T_box]),
- (rop.GUARD_NONNULL_CLASS, [t_box, U_box]),
- (rop.GUARD_NONNULL_CLASS, [u_box, T_box]),
- (rop.GUARD_NONNULL_CLASS, [null_box, T_box]),
- ]:
- assert self.execute_operation(opname, args, 'void') == None
- assert self.guard_failed
- def test_ooops(self):
- u1_box, U_box = self.alloc_instance(self.U)
- u2_box, U_box = self.alloc_instance(self.U)
- r = self.execute_operation(rop.PTR_EQ, [u1_box,
- u1_box.clonebox()], 'int')
- assert r.value == 1
- r = self.execute_operation(rop.PTR_NE, [u2_box,
- u2_box.clonebox()], 'int')
- assert r.value == 0
- r = self.execute_operation(rop.PTR_EQ, [u1_box, u2_box], 'int')
- assert r.value == 0
- r = self.execute_operation(rop.PTR_NE, [u2_box, u1_box], 'int')
- assert r.value == 1
- #
- null_box = self.null_instance()
- r = self.execute_operation(rop.PTR_EQ, [null_box,
- null_box.clonebox()], 'int')
- assert r.value == 1
- r = self.execute_operation(rop.PTR_EQ, [u1_box, null_box], 'int')
- assert r.value == 0
- r = self.execute_operation(rop.PTR_EQ, [null_box, u2_box], 'int')
- assert r.value == 0
- r = self.execute_operation(rop.PTR_NE, [null_box,
- null_box.clonebox()], 'int')
- assert r.value == 0
- r = self.execute_operation(rop.PTR_NE, [u2_box, null_box], 'int')
- assert r.value == 1
- r = self.execute_operation(rop.PTR_NE, [null_box, u1_box], 'int')
- assert r.value == 1
- def test_array_basic(self):
- a_box, A = self.alloc_array_of(rffi.SHORT, 342)
- arraydescr = self.cpu.arraydescrof(A)
- assert not arraydescr.is_array_of_pointers()
- #
- r = self.execute_operation(rop.ARRAYLEN_GC, [a_box],
- 'int', descr=arraydescr)
- assert r.value == 342
- r = self.execute_operation(rop.SETARRAYITEM_GC, [a_box, BoxInt(310),
- BoxInt(744)],
- 'void', descr=arraydescr)
- assert r is None
- r = self.execute_operation(rop.GETARRAYITEM_GC, [a_box, BoxInt(310)],
- 'int', descr=arraydescr)
- assert r.value == 744
- a_box, A = self.alloc_array_of(lltype.Signed, 342)
- arraydescr = self.cpu.arraydescrof(A)
- assert not arraydescr.is_array_of_pointers()
- #
- r = self.execute_operation(rop.ARRAYLEN_GC, [a_box],
- 'int', descr=arraydescr)
- assert r.value == 342
- r = self.execute_operation(rop.SETARRAYITEM_GC, [a_box, BoxInt(310),
- BoxInt(7441)],
- 'void', descr=arraydescr)
- assert r is None
- r = self.execute_operation(rop.GETARRAYITEM_GC, [a_box, BoxInt(310)],
- 'int', descr=arraydescr)
- assert r.value == 7441
- #
- a_box, A = self.alloc_array_of(lltype.Char, 11)
- arraydescr = self.cpu.arraydescrof(A)
- assert not arraydescr.is_array_of_pointers()
- r = self.execute_operation(rop.ARRAYLEN_GC, [a_box],
- 'int', descr=arraydescr)
- assert r.value == 11
- r = self.execute_operation(rop.SETARRAYITEM_GC, [a_box, BoxInt(4),
- BoxInt(150)],
- 'void', descr=arraydescr)
- assert r is None
- r = self.execute_operation(rop.SETARRAYITEM_GC, [a_box, BoxInt(3),
- BoxInt(160)],
- 'void', descr=arraydescr)
- assert r is None
- r = self.execute_operation(rop.GETARRAYITEM_GC, [a_box, BoxInt(4)],
- 'int', descr=arraydescr)
- assert r.value == 150
- r = self.execute_operation(rop.GETARRAYITEM_GC, [a_box, BoxInt(3)],
- 'int', descr=arraydescr)
- assert r.value == 160
- #
- if isinstance(A, lltype.GcArray):
- A = lltype.Ptr(A)
- b_box, B = self.alloc_array_of(A, 3)
- arraydescr = self.cpu.arraydescrof(B)
- assert arraydescr.is_array_of_pointers()
- r = self.execute_operation(rop.ARRAYLEN_GC, [b_box],
- 'int', descr=arraydescr)
- assert r.value == 3
- r = self.execute_operation(rop.SETARRAYITEM_GC, [b_box, BoxInt(1),
- a_box],
- 'void', descr=arraydescr)
- assert r is None
- r = self.execute_operation(rop.GETARRAYITEM_GC, [b_box, BoxInt(1)],
- 'ref', descr=arraydescr)
- assert r.value == a_box.value
- #
- # Unsigned should work the same as Signed
- a_box, A = self.alloc_array_of(lltype.Unsigned, 342)
- arraydescr = self.cpu.arraydescrof(A)
- assert not arraydescr.is_array_of_pointers()
- r = self.execute_operation(rop.ARRAYLEN_GC, [a_box],
- 'int', descr=arraydescr)
- assert r.value == 342
- r = self.execute_operation(rop.SETARRAYITEM_GC, [a_box, BoxInt(310),
- BoxInt(7441)],
- 'void', descr=arraydescr)
- assert r is None
- r = self.execute_operation(rop.GETARRAYITEM_GC, [a_box, BoxInt(310)],
- 'int', descr=arraydescr)
- assert r.value == 7441
- #
- # Bool should work the same as Char
- a_box, A = self.alloc_array_of(lltype.Bool, 311)
- arraydescr = self.cpu.arraydescrof(A)
- assert not arraydescr.is_array_of_pointers()
- r = self.execute_operation(rop.ARRAYLEN_GC, [a_box],
- 'int', descr=arraydescr)
- assert r.value == 311
- r = self.execute_operation(rop.SETARRAYITEM_GC, [a_box, BoxInt(304),
- BoxInt(1)],
- 'void', descr=arraydescr)
- assert r is None
- r = self.execute_operation(rop.SETARRAYITEM_GC, [a_box, BoxInt(303),
- BoxInt(0)],
- 'void', descr=arraydescr)
- assert r is None
- r = self.execute_operation(rop.SETARRAYITEM_GC, [a_box, BoxInt(302),
- BoxInt(1)],
- 'void', descr=arraydescr)
- assert r is None
- r = self.execute_operation(rop.GETARRAYITEM_GC, [a_box, BoxInt(304)],
- 'int', descr=arraydescr)
- assert r.value == 1
- r = self.execute_operation(rop.GETARRAYITEM_GC, [a_box, BoxInt(303)],
- 'int', descr=arraydescr)
- assert r.value == 0
- r = self.execute_operation(rop.GETARRAYITEM_GC, [a_box, BoxInt(302)],
- 'int', descr=arraydescr)
- assert r.value == 1
- if self.cpu.supports_floats:
- a_box, A = self.alloc_array_of(lltype.Float, 31)
- arraydescr = self.cpu.arraydescrof(A)
- self.execute_operation(rop.SETARRAYITEM_GC, [a_box, BoxInt(1),
- boxfloat(3.5)],
- 'void', descr=arraydescr)
- self.execute_operation(rop.SETARRAYITEM_GC, [a_box, BoxInt(2),
- constfloat(4.5)],
- 'void', descr=arraydescr)
- r = self.execute_operation(rop.GETARRAYITEM_GC, [a_box, BoxInt(1)],
- 'float', descr=arraydescr)
- assert r.getfloat() == 3.5
- r = self.execute_operation(rop.GETARRAYITEM_GC, [a_box, BoxInt(2)],
- 'float', descr=arraydescr)
- assert r.getfloat() == 4.5
- # For platforms where sizeof(INT) != sizeof(Signed) (ie, x86-64)
- a_box, A = self.alloc_array_of(rffi.INT, 342)
- arraydescr = self.cpu.arraydescrof(A)
- assert not arraydescr.is_array_of_pointers()
- r = self.execute_operation(rop.ARRAYLEN_GC, [a_box],
- 'int', descr=arraydescr)
- assert r.value == 342
- r = self.execute_operation(rop.SETARRAYITEM_GC, [a_box, BoxInt(310),
- BoxInt(7441)],
- 'void', descr=arraydescr)
- assert r is None
- r = self.execute_operation(rop.GETARRAYITEM_GC, [a_box, BoxInt(310)],
- 'int', descr=arraydescr)
- assert r.value == 7441
- def test_array_of_structs(self):
- TP = lltype.GcStruct('x')
- ITEM = lltype.Struct('x',
- ('vs', lltype.Signed),
- ('vu', lltype.Unsigned),
- ('vsc', rffi.SIGNEDCHAR),
- ('vuc', rffi.UCHAR),
- ('vss', rffi.SHORT),
- ('vus', rffi.USHORT),
- ('vsi', rffi.INT),
- ('vui', rffi.UINT),
- ('k', lltype.Float),
- ('p', lltype.Ptr(TP)))
- a_box, A = self.alloc_array_of(ITEM, 15)
- s_box, S = self.alloc_instance(TP)
- kdescr = self.cpu.interiorfielddescrof(A, 'k')
- pdescr = self.cpu.interiorfielddescrof(A, 'p')
- self.execute_operation(rop.SETINTERIORFIELD_GC, [a_box, BoxInt(3),
- boxfloat(1.5)],
- 'void', descr=kdescr)
- f = self.cpu.bh_getinteriorfield_gc_f(a_box.getref_base(), 3, kdescr)
- assert longlong.getrealfloat(f) == 1.5
- self.cpu.bh_setinteriorfield_gc_f(a_box.getref_base(), 3, kdescr, longlong.getfloatstorage(2.5))
- r = self.execute_operation(rop.GETINTERIORFIELD_GC, [a_box, BoxInt(3)],
- 'float', descr=kdescr)
- assert r.getfloat() == 2.5
- #
- NUMBER_FIELDS = [('vs', lltype.Signed),
- ('vu', lltype.Unsigned),
- ('vsc', rffi.SIGNEDCHAR),
- ('vuc', rffi.UCHAR),
- ('vss', rffi.SHORT),
- ('vus', rffi.USHORT),
- ('vsi', rffi.INT),
- ('vui', rffi.UINT)]
- for name, TYPE in NUMBER_FIELDS[::-1]:
- vdescr = self.cpu.interiorfielddescrof(A, name)
- self.execute_operation(rop.SETINTERIORFIELD_GC, [a_box, BoxInt(3),
- BoxInt(-15)],
- 'void', descr=vdescr)
- for name, TYPE in NUMBER_FIELDS:
- vdescr = self.cpu.interiorfielddescrof(A, name)
- i = self.cpu.bh_getinteriorfield_gc_i(a_box.getref_base(), 3,
- vdescr)
- assert i == rffi.cast(lltype.Signed, rffi.cast(TYPE, -15))
- for name, TYPE in NUMBER_FIELDS[::-1]:
- vdescr = self.cpu.interiorfielddescrof(A, name)
- self.cpu.bh_setinteriorfield_gc_i(a_box.getref_base(), 3,
- vdescr, -25)
- for name, TYPE in NUMBER_FIELDS:
- vdescr = self.cpu.interiorfielddescrof(A, name)
- r = self.execute_operation(rop.GETINTERIORFIELD_GC,
- [a_box, BoxInt(3)],
- 'int', descr=vdescr)
- assert r.getint() == rffi.cast(lltype.Signed, rffi.cast(TYPE, -25))
- #
- self.execute_operation(rop.SETINTERIORFIELD_GC, [a_box, BoxInt(4),
- s_box],
- 'void', descr=pdescr)
- r = self.cpu.bh_getinteriorfield_gc_r(a_box.getref_base(), 4, pdescr)
- assert r == s_box.getref_base()
- self.cpu.bh_setinteriorfield_gc_r(a_box.getref_base(), 3, pdescr,
- s_box.getref_base())
- r = self.execute_operation(rop.GETINTERIORFIELD_GC, [a_box, BoxInt(3)],
- 'ref', descr=pdescr)
- assert r.getref_base() == s_box.getref_base()
- def test_string_basic(self):
- s_box = self.alloc_string("hello\xfe")
- r = self.execute_operation(rop.STRLEN, [s_box], 'int')
- assert r.value == 6
- r = self.execute_operation(rop.STRGETITEM, [s_box, BoxInt(5)], 'int')
- assert r.value == 254
- r = self.execute_operation(rop.STRSETITEM, [s_box, BoxInt(4),
- BoxInt(153)], 'void')
- assert r is None
- r = self.execute_operation(rop.STRGETITEM, [s_box, BoxInt(5)], 'int')
- assert r.value == 254
- r = self.execute_operation(rop.STRGETITEM, [s_box, BoxInt(4)], 'int')
- assert r.value == 153
- def test_copystrcontent(self):
- s_box = self.alloc_string("abcdef")
- for s_box in [s_box, s_box.constbox()]:
- for srcstart_box in [BoxInt(2), ConstInt(2)]:
- for dststart_box in [BoxInt(3), ConstInt(3)]:
- for length_box in [BoxInt(4), ConstInt(4)]:
- for r_box_is_const in [False, True]:
- r_box = self.alloc_string("!???????!")
- if r_box_is_const:
- r_box = r_box.constbox()
- self.execute_operation(rop.COPYSTRCONTENT,
- [s_box, r_box,
- srcstart_box,
- dststart_box,
- length_box], 'void')
- assert self.look_string(r_box) == "!??cdef?!"
- def test_copyunicodecontent(self):
- s_box = self.alloc_unicode(u"abcdef")
- for s_box in [s_box, s_box.constbox()]:
- for srcstart_box in [BoxInt(2), ConstInt(2)]:
- for dststart_box in [BoxInt(3), ConstInt(3)]:
- for length_box in [BoxInt(4), ConstInt(4)]:
- for r_box_is_const in [False, True]:
- r_box = self.alloc_unicode(u"!???????!")
- if r_box_is_const:
- r_box = r_box.constbox()
- self.execute_operation(rop.COPYUNICODECONTENT,
- [s_box, r_box,
- srcstart_box,
- dststart_box,
- length_box], 'void')
- assert self.look_unicode(r_box) == u"!??cdef?!"
- def test_do_unicode_basic(self):
- u = self.cpu.bh_newunicode(5)
- self.cpu.bh_unicodesetitem(u, 4, 123)
- r = self.cpu.bh_unicodegetitem(u, 4)
- assert r == 123
- def test_unicode_basic(self):
- u_box = self.alloc_unicode(u"hello\u1234")
- r = self.execute_operation(rop.UNICODELEN, [u_box], 'int')
- assert r.value == 6
- r = self.execute_operation(rop.UNICODEGETITEM, [u_box, BoxInt(5)],
- 'int')
- assert r.value == 0x1234
- r = self.execute_operation(rop.UNICODESETITEM, [u_box, BoxInt(4),
- BoxInt(31313)], 'void')
- assert r is None
- r = self.execute_operation(rop.UNICODEGETITEM, [u_box, BoxInt(5)],
- 'int')
- assert r.value == 0x1234
- r = self.execute_operation(rop.UNICODEGETITEM, [u_box, BoxInt(4)],
- 'int')
- assert r.value == 31313
- def test_same_as(self):
- r = self.execute_operation(rop.SAME_AS, [ConstInt(5)], 'int')
- assert r.value == 5
- r = self.execute_operation(rop.SAME_AS, [BoxInt(5)], 'int')
- assert r.value == 5
- u_box = self.alloc_unicode(u"hello\u1234")
- r = self.execute_operation(rop.SAME_AS, [u_box.constbox()], 'ref')
- assert r.value == u_box.value
- r = self.execute_operation(rop.SAME_AS, [u_box], 'ref')
- assert r.value == u_box.value
- if self.cpu.supports_floats:
- r = self.execute_operation(rop.SAME_AS, [constfloat(5.5)], 'float')
- assert r.getfloat() == 5.5
- r = self.execute_operation(rop.SAME_AS, [boxfloat(5.5)], 'float')
- assert r.getfloat() == 5.5
- def test_virtual_ref(self):
- pass # VIRTUAL_REF must not reach the backend nowadays
- def test_virtual_ref_finish(self):
- pass # VIRTUAL_REF_FINISH must not reach the backend nowadays
- def test_jump(self):
- # this test generates small loops where the JUMP passes many
- # arguments of various types, shuffling them around.
- if self.cpu.supports_floats:
- numkinds = 3
- else:
- numkinds = 2
- seed = random.randrange(0, 10000)
- print 'Seed is', seed # or choose it by changing the previous line
- r = random.Random()
- r.seed(seed)
- for nb_args in range(50):
- …
Large files files are truncated, but you can click here to view the full file