Author: Armin Rigo <[email protected]>
Branch:
Changeset: r63808:e23dbce85236
Date: 2013-05-02 23:00 +0200
http://bitbucket.org/pypy/pypy/changeset/e23dbce85236/
Log: Fix the failing tests added in f81be71175fe:
- support for singlefloat return values
- if the backend says it doesn't support some of the types, don't
crash with a KeyError
Moreover, avoids casting a real longlong temporarily into a float.
This is frowned upon by now, because a small fraction of longlongs
don't cast correctly to float and back.
diff --git a/rpython/jit/codewriter/jtransform.py
b/rpython/jit/codewriter/jtransform.py
--- a/rpython/jit/codewriter/jtransform.py
+++ b/rpython/jit/codewriter/jtransform.py
@@ -1751,7 +1751,7 @@
def rewrite_op_jit_ffi_save_result(self, op):
kind = op.args[0].value
- assert kind in ('int', 'float')
+ assert kind in ('int', 'float', 'longlong', 'singlefloat')
return SpaceOperation('libffi_save_result_%s' % kind, op.args[1:],
None)
def rewrite_op_jit_force_virtual(self, op):
diff --git a/rpython/jit/metainterp/blackhole.py
b/rpython/jit/metainterp/blackhole.py
--- a/rpython/jit/metainterp/blackhole.py
+++ b/rpython/jit/metainterp/blackhole.py
@@ -1351,24 +1351,39 @@
def bhimpl_ll_read_timestamp():
return read_timestamp()
- @arguments("cpu", "i", "i", "i")
- def bhimpl_libffi_save_result_int(self, cif_description, exchange_buffer,
result):
- ARRAY = lltype.Ptr(rffi.CArray(lltype.Signed))
- cif_description = self.cast_int_to_ptr(cif_description,
CIF_DESCRIPTION_P)
- exchange_buffer = self.cast_int_to_ptr(exchange_buffer, rffi.CCHARP)
+ def _libffi_save_result(self, cif_description, exchange_buffer, result):
+ ARRAY = lltype.Ptr(rffi.CArray(lltype.typeOf(result)))
+ cast_int_to_ptr = self.cpu.cast_int_to_ptr
+ cif_description = cast_int_to_ptr(cif_description, CIF_DESCRIPTION_P)
+ exchange_buffer = cast_int_to_ptr(exchange_buffer, rffi.CCHARP)
#
data_out = rffi.ptradd(exchange_buffer,
cif_description.exchange_result)
rffi.cast(ARRAY, data_out)[0] = result
+ _libffi_save_result._annspecialcase_ = 'specialize:argtype(3)'
- @arguments("cpu", "i", "i", "f")
- def bhimpl_libffi_save_result_float(self, cif_description,
exchange_buffer, result):
+ @arguments("self", "i", "i", "i")
+ def bhimpl_libffi_save_result_int(self, cif_description,
+ exchange_buffer, result):
+ self._libffi_save_result(cif_description, exchange_buffer, result)
+
+ @arguments("self", "i", "i", "f")
+ def bhimpl_libffi_save_result_float(self, cif_description,
+ exchange_buffer, result):
result = longlong.getrealfloat(result)
- ARRAY = lltype.Ptr(rffi.CArray(lltype.Float))
- cif_description = self.cast_int_to_ptr(cif_description,
CIF_DESCRIPTION_P)
- exchange_buffer = self.cast_int_to_ptr(exchange_buffer, rffi.CCHARP)
- #
- data_out = rffi.ptradd(exchange_buffer,
cif_description.exchange_result)
- rffi.cast(ARRAY, data_out)[0] = result
+ self._libffi_save_result(cif_description, exchange_buffer, result)
+
+ @arguments("self", "i", "i", "f")
+ def bhimpl_libffi_save_result_longlong(self, cif_description,
+ exchange_buffer, result):
+ # 32-bit only: 'result' is here a LongLong
+ assert longlong.is_longlong(lltype.typeOf(result))
+ self._libffi_save_result(cif_description, exchange_buffer, result)
+
+ @arguments("self", "i", "i", "i")
+ def bhimpl_libffi_save_result_singlefloat(self, cif_description,
+ exchange_buffer, result):
+ result = longlong.int2singlefloat(result)
+ self._libffi_save_result(cif_description, exchange_buffer, result)
# ----------
diff --git a/rpython/jit/metainterp/pyjitpl.py
b/rpython/jit/metainterp/pyjitpl.py
--- a/rpython/jit/metainterp/pyjitpl.py
+++ b/rpython/jit/metainterp/pyjitpl.py
@@ -1190,8 +1190,8 @@
return self.metainterp.execute_and_record(rop.READ_TIMESTAMP, None)
@arguments("box", "box", "box")
- def opimpl_libffi_save_result_int(self, box_cif_description,
box_exchange_buffer,
- box_result):
+ def _opimpl_libffi_save_result(self, box_cif_description,
+ box_exchange_buffer, box_result):
from rpython.rtyper.lltypesystem import llmemory
from rpython.rlib.jit_libffi import CIF_DESCRIPTION_P
from rpython.jit.backend.llsupport.ffisupport import get_arg_descr
@@ -1208,10 +1208,14 @@
assert ofs % itemsize == 0 # alignment check (result)
self.metainterp.history.record(rop.SETARRAYITEM_RAW,
[box_exchange_buffer,
- ConstInt(ofs // itemsize),
box_result],
+ ConstInt(ofs // itemsize),
+ box_result],
None, descr)
- opimpl_libffi_save_result_float = opimpl_libffi_save_result_int
+ opimpl_libffi_save_result_int = _opimpl_libffi_save_result
+ opimpl_libffi_save_result_float = _opimpl_libffi_save_result
+ opimpl_libffi_save_result_longlong = _opimpl_libffi_save_result
+ opimpl_libffi_save_result_singlefloat = _opimpl_libffi_save_result
# ------------------------------
diff --git a/rpython/jit/metainterp/test/support.py
b/rpython/jit/metainterp/test/support.py
--- a/rpython/jit/metainterp/test/support.py
+++ b/rpython/jit/metainterp/test/support.py
@@ -14,7 +14,10 @@
def _get_jitcodes(testself, CPUClass, func, values, type_system,
- supports_longlong=False, translationoptions={}, **kwds):
+ supports_floats=True,
+ supports_longlong=False,
+ supports_singlefloats=False,
+ translationoptions={}, **kwds):
from rpython.jit.codewriter import support
class FakeJitCell(object):
@@ -68,8 +71,9 @@
cw.debug = True
testself.cw = cw
policy = JitPolicy()
- policy.set_supports_floats(True)
+ policy.set_supports_floats(supports_floats)
policy.set_supports_longlong(supports_longlong)
+ policy.set_supports_singlefloats(supports_singlefloats)
graphs = cw.find_all_graphs(policy)
if kwds.get("backendopt"):
backend_optimizations(rtyper.annotator.translator, graphs=graphs)
diff --git a/rpython/jit/metainterp/test/test_fficall.py
b/rpython/jit/metainterp/test/test_fficall.py
--- a/rpython/jit/metainterp/test/test_fficall.py
+++ b/rpython/jit/metainterp/test/test_fficall.py
@@ -5,7 +5,7 @@
from rpython.rtyper.lltypesystem import lltype, rffi
from rpython.rtyper.annlowlevel import llhelper
from rpython.jit.metainterp.test.support import LLJitMixin
-from rpython.jit.codewriter.longlong import is_longlong
+from rpython.jit.codewriter.longlong import is_longlong, is_64_bit
from rpython.rlib import jit
from rpython.rlib import jit_libffi
from rpython.rlib.jit_libffi import (types, CIF_DESCRIPTION, FFI_TYPE_PP,
@@ -45,7 +45,12 @@
class FfiCallTests(object):
- def _run(self, atypes, rtype, avalues, rvalue,
expected_call_release_gil=1):
+ def _run(self, atypes, rtype, avalues, rvalue,
+ expected_call_release_gil=1,
+ supports_floats=True,
+ supports_longlong=True,
+ supports_singlefloats=True):
+
cif_description = get_description(atypes, rtype)
def verify(*args):
@@ -100,17 +105,30 @@
data = rffi.ptradd(exbuf, ofs)
res = rffi.cast(lltype.Ptr(TYPE), data)[0]
lltype.free(exbuf, flavor='raw')
+ if lltype.typeOf(res) is lltype.SingleFloat:
+ res = float(res)
return res
+ def matching_result(res, rvalue):
+ if rvalue is None:
+ return res == 654321
+ if isinstance(rvalue, r_singlefloat):
+ rvalue = float(rvalue)
+ return res == rvalue
+
with FakeFFI(fake_call_impl_any):
res = f()
- assert res == rvalue or (res, rvalue) == (654321, None)
- res = self.interp_operations(f, [])
+ assert matching_result(res, rvalue)
+ res = self.interp_operations(f, [],
+ supports_floats = supports_floats,
+ supports_longlong = supports_longlong,
+ supports_singlefloats = supports_singlefloats)
if is_longlong(FUNC.RESULT):
- # longlongs are passed around as floats inside the JIT, we
- # need to convert it back before checking the value
+ # longlongs are returned as floats, but that's just
+ # an inconvenience of interp_operations(). Normally both
+ # longlong and floats are passed around as longlongs.
res = float2longlong(res)
- assert res == rvalue or (res, rvalue) == (654321, None)
+ assert matching_result(res, rvalue)
self.check_operations_history(call_may_force=0,
call_release_gil=expected_call_release_gil)
@@ -123,22 +141,24 @@
[-123456*j for j in range(i)],
-42434445)
- def test_simple_call_float(self):
- self._run([types.double] * 2, types.double, [45.6, 78.9], -4.2)
+ def test_simple_call_float(self, **kwds):
+ self._run([types.double] * 2, types.double, [45.6, 78.9], -4.2, **kwds)
- def test_simple_call_longlong(self):
+ def test_simple_call_longlong(self, **kwds):
maxint32 = 2147483647
a = r_longlong(maxint32) + 1
b = r_longlong(maxint32) + 2
- self._run([types.slonglong] * 2, types.slonglong, [a, b], a)
+ self._run([types.slonglong] * 2, types.slonglong, [a, b], a, **kwds)
def test_simple_call_singlefloat_args(self):
- self._run([types.float] * 2, types.double, [r_singlefloat(10.5),
- r_singlefloat(31.5)], -4.5)
+ self._run([types.float] * 2, types.double,
+ [r_singlefloat(10.5), r_singlefloat(31.5)],
+ -4.5)
- def test_simple_call_singlefloat(self):
- self._run([types.float] * 2, types.float, [r_singlefloat(10.5),
- r_singlefloat(31.5)], -4.5)
+ def test_simple_call_singlefloat(self, **kwds):
+ self._run([types.float] * 2, types.float,
+ [r_singlefloat(10.5), r_singlefloat(31.5)],
+ r_singlefloat(-4.5), **kwds)
def test_simple_call_longdouble(self):
# longdouble is not supported, so we expect NOT to generate a
call_release_gil
@@ -279,23 +299,19 @@
lltype.free(atypes, flavor='raw')
- def _patch_cpuclass(self, **change):
- def make_cpu(*args, **kwds):
- cpu = CPUClass(*args, **kwds)
- for key, value in change.items():
- setattr(cpu, key, value)
- return cpu
- CPUClass = self.CPUClass
- self.CPUClass = make_cpu
-
def test_simple_call_float_unsupported(self):
- self._patch_cpuclass(supports_floats=False)
- self.test_simple_call_float()
+ self.test_simple_call_float(supports_floats=False,
+ expected_call_release_gil=0)
def test_simple_call_longlong_unsupported(self):
- self._patch_cpuclass(supports_longlong=False)
- self.test_simple_call_longlong()
+ self.test_simple_call_longlong(supports_longlong=False,
+ expected_call_release_gil=is_64_bit)
def test_simple_call_singlefloat_unsupported(self):
- self._patch_cpuclass(supports_singlefloats=False)
- self.test_simple_call_singlefloat()
+ self.test_simple_call_singlefloat(supports_singlefloats=False,
+ expected_call_release_gil=0)
+
+ def test_simple_call_float_even_if_other_unsupported(self):
+ self.test_simple_call_float(supports_longlong=False,
+ supports_singlefloats=False)
+ # this is the default: expected_call_release_gil=1
diff --git a/rpython/rlib/jit_libffi.py b/rpython/rlib/jit_libffi.py
--- a/rpython/rlib/jit_libffi.py
+++ b/rpython/rlib/jit_libffi.py
@@ -2,6 +2,7 @@
from rpython.rtyper.lltypesystem import lltype, rffi
from rpython.rtyper.extregistry import ExtRegistryEntry
from rpython.rlib import clibffi, jit
+from rpython.rlib.rarithmetic import r_longlong, r_singlefloat
from rpython.rlib.nonconst import NonConstant
@@ -107,12 +108,14 @@
reskind = types.getkind(cif_description.rtype)
if reskind == 'v':
jit_ffi_call_impl_void(cif_description, func_addr, exchange_buffer)
- elif reskind == 'f' or reskind == 'L': # L is for longlongs, on 32bit
- result = jit_ffi_call_impl_float(cif_description, func_addr,
exchange_buffer)
- jit_ffi_save_result('float', cif_description, exchange_buffer, result)
elif reskind == 'i' or reskind == 'u':
- result = jit_ffi_call_impl_int(cif_description, func_addr,
exchange_buffer)
- jit_ffi_save_result('int', cif_description, exchange_buffer, result)
+ _do_ffi_call_int(cif_description, func_addr, exchange_buffer)
+ elif reskind == 'f':
+ _do_ffi_call_float(cif_description, func_addr, exchange_buffer)
+ elif reskind == 'L': # L is for longlongs, on 32bit
+ _do_ffi_call_longlong(cif_description, func_addr, exchange_buffer)
+ elif reskind == 'S': # SingleFloat
+ _do_ffi_call_singlefloat(cif_description, func_addr, exchange_buffer)
else:
# the result kind is not supported: we disable the jit_ffi_call
# optimization by calling directly jit_ffi_call_impl_any, so the JIT
@@ -123,6 +126,30 @@
jit_ffi_call_impl_any(cif_description, func_addr, exchange_buffer)
+def _do_ffi_call_int(cif_description, func_addr, exchange_buffer):
+ result = jit_ffi_call_impl_int(cif_description, func_addr,
+ exchange_buffer)
+ jit_ffi_save_result('int', cif_description, exchange_buffer, result)
+
+def _do_ffi_call_float(cif_description, func_addr, exchange_buffer):
+ # a separate function in case the backend doesn't support floats
+ result = jit_ffi_call_impl_float(cif_description, func_addr,
+ exchange_buffer)
+ jit_ffi_save_result('float', cif_description, exchange_buffer, result)
+
+def _do_ffi_call_longlong(cif_description, func_addr, exchange_buffer):
+ # a separate function in case the backend doesn't support longlongs
+ result = jit_ffi_call_impl_longlong(cif_description, func_addr,
+ exchange_buffer)
+ jit_ffi_save_result('longlong', cif_description, exchange_buffer, result)
+
+def _do_ffi_call_singlefloat(cif_description, func_addr, exchange_buffer):
+ # a separate function in case the backend doesn't support singlefloats
+ result = jit_ffi_call_impl_singlefloat(cif_description, func_addr,
+ exchange_buffer)
+ jit_ffi_save_result('singlefloat', cif_description, exchange_buffer,result)
+
+
# we must return a NonConstant else we get the constant -1 as the result of
# the flowgraph, and the codewriter does not produce a box for the
# result. Note that when not-jitted, the result is unused, but when jitted the
@@ -139,6 +166,16 @@
return NonConstant(-1.0)
@jit.oopspec("libffi_call(cif_description,func_addr,exchange_buffer)")
+def jit_ffi_call_impl_longlong(cif_description, func_addr, exchange_buffer):
+ jit_ffi_call_impl_any(cif_description, func_addr, exchange_buffer)
+ return r_longlong(-1)
+
[email protected]("libffi_call(cif_description,func_addr,exchange_buffer)")
+def jit_ffi_call_impl_singlefloat(cif_description, func_addr, exchange_buffer):
+ jit_ffi_call_impl_any(cif_description, func_addr, exchange_buffer)
+ return r_singlefloat(-1.0)
+
[email protected]("libffi_call(cif_description,func_addr,exchange_buffer)")
def jit_ffi_call_impl_void(cif_description, func_addr, exchange_buffer):
jit_ffi_call_impl_any(cif_description, func_addr, exchange_buffer)
return None
@@ -175,7 +212,7 @@
def compute_result_annotation(self, kind_s, *args_s):
from rpython.annotator import model as annmodel
assert isinstance(kind_s, annmodel.SomeString)
- assert kind_s.const in ('int', 'float')
+ assert kind_s.const in ('int', 'float', 'longlong', 'singlefloat')
def specialize_call(self, hop):
hop.exception_cannot_occur()
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit