Author: Philip Jenvey <pjen...@underboss.org>
Branch: py3k
Changeset: r63813:dbaf0bdc00d4
Date: 2013-05-02 17:04 -0700
http://bitbucket.org/pypy/pypy/changeset/dbaf0bdc00d4/

Log:    merge default

diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-2.0.rst
copy from pypy/doc/whatsnew-head.rst
copy to pypy/doc/whatsnew-2.0.rst
diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -1,140 +1,8 @@
 ======================
-What's new in PyPy 2.0
+What's new in PyPy 2.1
 ======================
 
-.. this is a revision shortly after release-2.0-beta1
-.. startrev: 0e6161a009c6
+.. this is a revision shortly after release-2.0
+.. startrev: a13c07067613
 
-.. branch: split-rpython
-Split rpython and pypy into seperate directories
 
-.. branch: callback-jit
-Callbacks from C are now better JITted
-
-.. branch: fix-jit-logs
-
-.. branch: remove-globals-in-jit
-
-.. branch: length-hint
-Implement __lenght_hint__ according to PEP 424
-
-.. branch: numpypy-longdouble
-Long double support for numpypy
-
-.. branch: numpypy-disable-longdouble
-Since r_longdouble support is missing, disable all longdouble and derivative
-dtypes using ENABLED_LONG_DOUBLE = False
-
-.. branch: numpypy-real-as-view
-Convert real, imag from ufuncs to views. This involves the beginning of
-view() functionality
-
-.. branch: indexing-by-array
-Adds indexing by scalar, adds int conversion from scalar and single element 
array,
-fixes compress, indexing by an array with a smaller shape and the indexed 
object.
-
-.. branch: str-dtype-improvement
-Allow concatenation of str and numeric arrays
-
-.. branch: signatures
-Improved RPython typing
-
-.. branch: rpython-bytearray
-Rudimentary support for bytearray in RPython
-
-.. branch: refactor-call_release_gil
-Fix a bug which caused cffi to return the wrong result when calling a C
-function which calls a Python callback which forces the frames
-
-.. branch: virtual-raw-mallocs
-JIT optimizations which make cffi calls even faster, by removing the need to
-allocate a temporary buffer where to store the arguments.
-
-.. branch: improve-docs-2
-Improve documents and straighten out links
-
-.. branch: fast-newarray
-Inline the fast path of newarray in the assembler.
-Disabled on ARM until we fix issues.
-
-.. branch: reflex-support
-Allow dynamic loading of a (Reflex) backend that implements the C-API needed
-to provide reflection information
-
-.. branches we don't care about
-.. branch: autoreds
-.. branch: kill-faking
-.. branch: improved_ebnfparse_error
-.. branch: task-decorator
-.. branch: fix-e4fa0b2
-.. branch: win32-fixes
-.. branch: numpy-unify-methods
-.. branch: fix-version-tool
-.. branch: popen2-removal
-.. branch: pickle-dumps
-.. branch: scalar_get_set
-
-.. branch: release-2.0-beta1
-
-.. branch: remove-PYPY_NOT_MAIN_FILE
-
-.. branch: missing-jit-operations
-
-.. branch: fix-lookinside-iff-oopspec
-Fixed the interaction between two internal tools for controlling the JIT.
-
-.. branch: inline-virtualref-2
-Better optimized certain types of frame accesses in the JIT, particularly
-around exceptions that escape the function they were raised in.
-
-.. branch: missing-ndarray-attributes
-Some missing attributes from ndarrays
-
-.. branch: cleanup-tests
-Consolidated the lib_pypy/pypy_test and pypy/module/test_lib_pypy tests into
-one directory for reduced confusion and so they all run nightly.
-
-.. branch: unquote-faster
-.. branch: urlparse-unquote-faster
-
-.. branch: signal-and-thread
-Add "__pypy__.thread.signals_enabled", a context manager. Can be used in a
-non-main thread to enable the processing of signal handlers in that thread.
-
-.. branch: coding-guide-update-rlib-refs
-.. branch: rlib-doc-rpython-refs
-.. branch: clean-up-remaining-pypy-rlib-refs
-
-.. branch: enumerate-rstr
-Support enumerate() over rstr types.
-
-.. branch: cleanup-numpypy-namespace
-Cleanup _numpypy and numpypy namespaces to more closely resemble numpy.
-
-.. branch: kill-flowobjspace
-Random cleanups to hide FlowObjSpace from public view.
-
-.. branch: vendor-rename
-
-.. branch: jitframe-on-heap
-Moves optimized JIT frames from stack to heap. As a side effect it enables
-stackless to work well with the JIT on PyPy. Also removes a bunch of code from
-the GC which fixes cannot find gc roots.
-
-.. branch: pycon2013-doc-fixes
-Documentation fixes after going through the docs at PyCon 2013 sprint.
-
-.. branch: extregistry-refactor
-
-.. branch: remove-list-smm
-.. branch: bridge-logging
-.. branch: curses_cffi
-cffi implementation of _curses
-
-.. branch: sqlite-cffi
-cffi implementation of sqlite3
-
-.. branch: release-2.0-beta2
-.. branch: unbreak-freebsd
-
-.. branch: virtualref-virtualizable
diff --git a/pypy/module/imp/importing.py b/pypy/module/imp/importing.py
--- a/pypy/module/imp/importing.py
+++ b/pypy/module/imp/importing.py
@@ -31,12 +31,8 @@
 # PY_CODERESOURCE = 8
 IMP_HOOK = 9
 
-if sys.platform == 'win32':
-    SO = ".pyd"
-else:
-    SO = ".so"
+SO = '.pyd' if _WIN32 else '.so'
 DEFAULT_SOABI = 'pypy-%d%d' % PYPY_VERSION[:2]
-CHECK_FOR_PYW = sys.platform == 'win32'
 
 PYC_TAG = 'pypy-%d%d' % PYPY_VERSION[:2]
 
@@ -70,7 +66,7 @@
         return PY_SOURCE, ".py", "U"
 
     # on Windows, also check for a .pyw file
-    if CHECK_FOR_PYW:
+    if _WIN32:
         pyfile = filepart + ".pyw"
         if file_exists(pyfile):
             return PY_SOURCE, ".pyw", "U"
diff --git a/rpython/jit/backend/arm/codebuilder.py 
b/rpython/jit/backend/arm/codebuilder.py
--- a/rpython/jit/backend/arm/codebuilder.py
+++ b/rpython/jit/backend/arm/codebuilder.py
@@ -49,6 +49,70 @@
             instr = self._encode_reg_list(cond << 28 | 0x92D << 16, regs)
         self.write32(instr)
 
+    def STM(self, base, regs, write_back=False, cond=cond.AL):
+        assert len(regs) > 0
+        instr = (cond << 28
+                | 0x11 << 23
+                | (1 if write_back else 0) << 21
+                | (base & 0xF) << 16)
+        instr = self._encode_reg_list(instr, regs)
+        self.write32(instr)
+
+    def LDM(self, base, regs, write_back=False, cond=cond.AL):
+        assert len(regs) > 0
+        instr = (cond << 28
+                | 0x11 << 23
+                | (1 if write_back else 0) << 21
+                | 1 << 20
+                | (base & 0xF) << 16)
+        instr = self._encode_reg_list(instr, regs)
+        self.write32(instr)
+
+    def VSTM(self, base, regs, write_back=False, cond=cond.AL):
+        # encoding T1
+        P = 0
+        U = 1
+        nregs = len(regs)
+        assert nregs > 0 and nregs <= 16
+        freg = regs[0]
+        D = (freg & 0x10) >> 4
+        Dd = (freg & 0xF)
+        nregs *= 2
+        instr = (cond << 28
+                | 3 << 26
+                | P << 24
+                | U << 23
+                | D << 22
+                | (1 if write_back else 0) << 21
+                | (base & 0xF) << 16
+                | Dd << 12
+                | 0xB << 8
+                | nregs)
+        self.write32(instr)
+
+    def VLDM(self, base, regs, write_back=False, cond=cond.AL):
+        # encoding T1
+        P = 0
+        U = 1
+        nregs = len(regs)
+        assert nregs > 0 and nregs <= 16
+        freg = regs[0]
+        D = (freg & 0x10) >> 4
+        Dd = (freg & 0xF)
+        nregs *= 2
+        instr = (cond << 28
+                | 3 << 26
+                | P << 24
+                | U << 23
+                | D << 22
+                | (1 if write_back else 0) << 21
+                | 1 << 20
+                | (base & 0xF) << 16
+                | Dd << 12
+                | 0xB << 8
+                | nregs)
+        self.write32(instr)
+
     def VPUSH(self, regs, cond=cond.AL):
         nregs = len(regs)
         assert nregs > 0 and nregs <= 16
diff --git a/rpython/jit/backend/arm/test/test_assembler.py 
b/rpython/jit/backend/arm/test/test_assembler.py
--- a/rpython/jit/backend/arm/test/test_assembler.py
+++ b/rpython/jit/backend/arm/test/test_assembler.py
@@ -6,11 +6,16 @@
 from rpython.jit.backend.arm.test.support import run_asm
 from rpython.jit.backend.detect_cpu import getcpuclass
 from rpython.jit.metainterp.resoperation import rop
+from rpython.jit.codewriter import longlong
 
 from rpython.rtyper.annlowlevel import llhelper
 from rpython.rtyper.lltypesystem import lltype, rffi
 from rpython.jit.metainterp.history import JitCellToken
 from rpython.jit.backend.model import CompiledLoopToken
+from rpython.rtyper.lltypesystem import lltype, llmemory, rffi
+from rpython.rtyper.annlowlevel import llhelper
+from rpython.rlib.objectmodel import specialize
+from rpython.rlib.debug import ll_assert
 
 CPU = getcpuclass()
 
@@ -247,7 +252,91 @@
         self.a.mc.ADD_ri(r.sp.value, r.sp.value, 8)
         self.a.gen_func_epilog()
         assert run_asm(self.a) == x
+    
+    def test_stm(self):
+        container = lltype.malloc(lltype.Array(lltype.Signed, 
hints={'nolength': True}), 10, flavor='raw')
+        self.a.gen_func_prolog()
+        self.a.mc.gen_load_int(r.ip.value, rffi.cast(lltype.Signed, container))
+        for x in range(10):
+            self.a.mc.gen_load_int(x, x)
+        self.a.mc.STM(r.ip.value, [x for x in range(10)])
+        self.a.gen_func_epilog()
+        run_asm(self.a)
+        for x in range(10):
+            assert container[x] == x
+        lltype.free(container, flavor='raw')
 
+    def test_ldm(self):
+        container = lltype.malloc(lltype.Array(lltype.Signed, 
hints={'nolength': True}), 10, flavor='raw')
+        for x in range(10):
+            container[x] = x
+        self.a.gen_func_prolog()
+        self.a.mc.gen_load_int(r.ip.value, rffi.cast(lltype.Signed, container))
+        self.a.mc.LDM(r.ip.value, [x for x in range(10)])
+        for x in range(1, 10):
+            self.a.mc.ADD_rr(0, 0, x)
+        self.a.gen_func_epilog()
+        res = run_asm(self.a)
+        assert res == sum(range(10))
+        lltype.free(container, flavor='raw')
+
+    def test_vstm(self):
+        n = 14
+        source_container = lltype.malloc(lltype.Array(longlong.FLOATSTORAGE,
+            hints={'nolength': True}), n, flavor='raw')
+        target_container = lltype.malloc(lltype.Array(longlong.FLOATSTORAGE,
+            hints={'nolength': True}), n, flavor='raw')
+        for x in range(n):
+            source_container[x] = longlong.getfloatstorage(float("%d.%d" % 
(x,x)))
+        self.a.gen_func_prolog()
+        for x in range(n):
+            self.a.mc.ADD_ri(r.ip.value, r.ip.value, 8)
+            self.a.mc.VLDR(n, r.ip.value)
+        self.a.mc.gen_load_int(r.ip.value, rffi.cast(lltype.Signed, 
target_container))
+        self.a.mc.VSTM(r.ip.value, [x for x in range(n)])
+        self.a.gen_func_epilog()
+        run_asm(self.a)
+        for d in range(n):
+            res = longlong.getrealfloat(target_container[0]) == float("%d.%d" 
% (d,d))
+        lltype.free(source_container, flavor='raw')
+        lltype.free(target_container, flavor='raw')
+
+    def test_vldm(self):
+        n = 14
+        container = lltype.malloc(lltype.Array(longlong.FLOATSTORAGE,
+                                hints={'nolength': True}), n, flavor='raw')
+        for x in range(n):
+            container[x] = longlong.getfloatstorage(float("%d.%d" % (x,x)))
+        self.a.gen_func_prolog()
+        self.a.mc.gen_load_int(r.ip.value, rffi.cast(lltype.Signed, container))
+        self.a.mc.VLDM(r.ip.value, [x for x in range(n)])
+        for x in range(1, n):
+            self.a.mc.VADD(0, 0, x)
+        self.a.mc.VSTR(r.d0.value, r.ip.value)
+        self.a.gen_func_epilog()
+        res = run_asm(self.a)
+        assert longlong.getrealfloat(container[0]) == sum([float("%d.%d" % 
(d,d)) for d in range(n)])
+        lltype.free(container, flavor='raw')
+
+    def test_vstm_vldm_combined(self):
+        n = 14
+        source_container = lltype.malloc(lltype.Array(longlong.FLOATSTORAGE,
+            hints={'nolength': True}), n, flavor='raw')
+        target_container = lltype.malloc(lltype.Array(longlong.FLOATSTORAGE,
+            hints={'nolength': True}), n, flavor='raw')
+        for x in range(n):
+            source_container[x] = longlong.getfloatstorage(float("%d.%d" % 
(x,x)))
+        self.a.gen_func_prolog()
+        self.a.mc.gen_load_int(r.ip.value, rffi.cast(lltype.Signed, 
source_container))
+        self.a.mc.VLDM(r.ip.value, [x for x in range(n)])
+        self.a.mc.gen_load_int(r.ip.value, rffi.cast(lltype.Signed, 
target_container))
+        self.a.mc.VSTM(r.ip.value, [x for x in range(n)])
+        self.a.gen_func_epilog()
+        run_asm(self.a)
+        for d in range(n):
+            res = longlong.getrealfloat(target_container[0]) == float("%d.%d" 
% (d,d))
+        lltype.free(source_container, flavor='raw')
+        lltype.free(target_container, flavor='raw')
 
 def callme(inp):
     i = inp + 10
diff --git a/rpython/jit/backend/arm/test/test_instr_codebuilder.py 
b/rpython/jit/backend/arm/test/test_instr_codebuilder.py
--- a/rpython/jit/backend/arm/test/test_instr_codebuilder.py
+++ b/rpython/jit/backend/arm/test/test_instr_codebuilder.py
@@ -139,6 +139,22 @@
     def test_push_raises_sp(self):
         assert py.test.raises(AssertionError, 'self.cb.PUSH([r.sp.value])')
 
+    def test_stm(self):
+        self.cb.STM(r.fp.value, [reg.value for reg in r.caller_resp], 
cond=conditions.AL)
+        self.assert_equal('STM fp, {r0, r1, r2, r3}')
+
+    def test_ldm(self):
+        self.cb.LDM(r.fp.value, [reg.value for reg in r.caller_resp], 
cond=conditions.AL)
+        self.assert_equal('LDM fp, {r0, r1, r2, r3}')
+
+    def test_vstm(self):
+        self.cb.VSTM(r.fp.value, [reg.value for reg in r.caller_vfp_resp], 
cond=conditions.AL)
+        self.assert_equal('VSTM fp, {d0, d1, d2, d3, d4, d5, d6, d7}')
+
+    def test_vldm(self):
+        self.cb.VLDM(r.fp.value, [reg.value for reg in r.caller_vfp_resp], 
cond=conditions.AL)
+        self.assert_equal('VLDM fp, {d0, d1, d2, d3, d4, d5, d6, d7}')
+
     def test_pop(self):
         self.cb.POP([reg.value for reg in r.caller_resp], cond=conditions.AL)
         self.assert_equal('POP {r0, r1, r2, r3}')
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):
@@ -67,9 +70,16 @@
     cw = codewriter.CodeWriter(cpu, [FakeJitDriverSD()])
     cw.debug = True
     testself.cw = cw
+    if supports_floats and not cpu.supports_floats:
+        py.test.skip("this test requires supports_floats=True")
+    if supports_longlong and not cpu.supports_longlong:
+        py.test.skip("this test requires supports_longlong=True")
+    if supports_singlefloats and not cpu.supports_singlefloats:
+        py.test.skip("this test requires supports_singlefloats=True")
     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,13 +5,13 @@
 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,
                                      jit_ffi_call, jit_ffi_save_result)
 from rpython.rlib.unroll import unrolling_iterable
-from rpython.rlib.rarithmetic import intmask, r_longlong
+from rpython.rlib.rarithmetic import intmask, r_longlong, r_singlefloat
 from rpython.rlib.longlong2float import float2longlong
 
 def get_description(atypes, rtype):
@@ -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):
@@ -67,7 +72,11 @@
             for avalue in unroll_avalues:
                 TYPE = rffi.CArray(lltype.typeOf(avalue))
                 data = rffi.ptradd(exchange_buffer, ofs)
-                assert rffi.cast(lltype.Ptr(TYPE), data)[0] == avalue
+                got = rffi.cast(lltype.Ptr(TYPE), data)[0]
+                if lltype.typeOf(avalue) is lltype.SingleFloat:
+                    got = float(got)
+                    avalue = float(avalue)
+                assert got == avalue
                 ofs += 16
             if rvalue is not None:
                 write_rvalue = rvalue
@@ -96,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)
 
@@ -119,14 +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)
+
+    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
@@ -266,3 +298,20 @@
         assert res == math.sin(1.23)
 
         lltype.free(atypes, flavor='raw')
+
+    def test_simple_call_float_unsupported(self):
+        self.test_simple_call_float(supports_floats=False,
+                                    expected_call_release_gil=0)
+
+    def test_simple_call_longlong_unsupported(self):
+        self.test_simple_call_longlong(supports_longlong=False,
+                                       expected_call_release_gil=is_64_bit)
+
+    def test_simple_call_singlefloat_unsupported(self):
+        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)
+
+@jit.oopspec("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)
+
+@jit.oopspec("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
pypy-commit@python.org
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to