[pypy-commit] pypy default: Two new performance tests, with corresponding fixes (likely broken by 749bf9a13d9c)
arigo
noreply at buildbot.pypy.org
Fri May 15 20:17:27 CEST 2015
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r77342:a1a494787f41
Date: 2015-05-15 20:17 +0200
http://bitbucket.org/pypy/pypy/changeset/a1a494787f41/
Log: Two new performance tests, with corresponding fixes (likely broken
by 749bf9a13d9c)
diff --git a/pypy/module/_cffi_backend/ccallback.py b/pypy/module/_cffi_backend/ccallback.py
--- a/pypy/module/_cffi_backend/ccallback.py
+++ b/pypy/module/_cffi_backend/ccallback.py
@@ -1,7 +1,7 @@
"""
Callbacks.
"""
-import os
+import sys, os
from rpython.rlib import clibffi, rweakref, jit, jit_libffi
from rpython.rlib.objectmodel import compute_unique_id, keepalive_until_here
@@ -14,6 +14,8 @@
from pypy.module._cffi_backend.ctypeprim import W_CTypePrimitiveSigned
from pypy.module._cffi_backend.ctypevoid import W_CTypeVoid
+BIG_ENDIAN = sys.byteorder == 'big'
+
# ____________________________________________________________
@@ -147,7 +149,7 @@
# zero extension: fill the '*result' with zeros, and (on big-
# endian machines) correct the 'result' pointer to write to
misc._raw_memclear(ll_res, SIZE_OF_FFI_ARG)
- if jit_libffi.BIG_ENDIAN:
+ if BIG_ENDIAN:
diff = SIZE_OF_FFI_ARG - fresult.size
ll_res = rffi.ptradd(ll_res, diff)
#
diff --git a/pypy/module/pypyjit/test_pypy_c/test_ffi.py b/pypy/module/pypyjit/test_pypy_c/test_ffi.py
--- a/pypy/module/pypyjit/test_pypy_c/test_ffi.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_ffi.py
@@ -207,6 +207,88 @@
guard_no_exception(descr=...)
""", ignore_ops=['guard_not_invalidated'])
+ def test__cffi_call_c_int(self):
+ def main():
+ import os
+ try:
+ import _cffi_backend
+ except ImportError:
+ sys.stderr.write('SKIP: cannot import _cffi_backend\n')
+ return 0
+
+ libc = _cffi_backend.load_library(None)
+ BInt = _cffi_backend.new_primitive_type("int")
+ BClose = _cffi_backend.new_function_type([BInt], BInt)
+ _dup = libc.load_function(BClose, 'dup')
+ i = 0
+ fd0, fd1 = os.pipe()
+ while i < 300:
+ tmp = _dup(fd0) # ID: cfficall
+ os.close(tmp)
+ i += 1
+ os.close(fd0)
+ os.close(fd1)
+ BLong = _cffi_backend.new_primitive_type("long")
+ return 42
+ #
+ log = self.run(main, [])
+ assert log.result == 42
+ loop, = log.loops_by_filename(self.filepath)
+ if sys.maxint > 2**32:
+ extra = "i98 = int_signext(i97, 4)"
+ else:
+ extra = ""
+ assert loop.match_by_id('cfficall', """
+ p96 = force_token()
+ setfield_gc(p0, p96, descr=<FieldP pypy.interpreter.pyframe.PyFrame.vable_token .>)
+ i97 = call_release_gil(91, i59, i50, descr=<Calli 4 i EF=7 OS=62>)
+ guard_not_forced(descr=...)
+ guard_no_exception(descr=...)
+ %s
+ """ % extra, ignore_ops=['guard_not_invalidated'])
+
+ def test__cffi_call_size_t(self):
+ def main():
+ import os
+ try:
+ import _cffi_backend
+ except ImportError:
+ sys.stderr.write('SKIP: cannot import _cffi_backend\n')
+ return 0
+
+ libc = _cffi_backend.load_library(None)
+ BInt = _cffi_backend.new_primitive_type("int")
+ BSizeT = _cffi_backend.new_primitive_type("size_t")
+ BChar = _cffi_backend.new_primitive_type("char")
+ BCharP = _cffi_backend.new_pointer_type(BChar)
+ BWrite = _cffi_backend.new_function_type([BInt, BCharP, BSizeT],
+ BSizeT) # not signed here!
+ _write = libc.load_function(BWrite, 'write')
+ i = 0
+ fd0, fd1 = os.pipe()
+ buffer = _cffi_backend.newp(BCharP, 'A')
+ while i < 300:
+ tmp = _write(fd1, buffer, 1) # ID: cfficall
+ assert tmp == 1
+ assert os.read(fd0, 2) == 'A'
+ i += 1
+ os.close(fd0)
+ os.close(fd1)
+ return 42
+ #
+ log = self.run(main, [])
+ assert log.result == 42
+ loop, = log.loops_by_filename(self.filepath)
+ assert loop.match_by_id('cfficall', """
+ p96 = force_token()
+ setfield_gc(p0, p96, descr=<FieldP pypy.interpreter.pyframe.PyFrame.vable_token .>)
+ i97 = call_release_gil(91, i59, i10, i12, 1, descr=<Calli . iii EF=7 OS=62>)
+ guard_not_forced(descr=...)
+ guard_no_exception(descr=...)
+ p98 = call(ConstClass(fromrarith_int__r_uint), i97, descr=<Callr . i EF=4>)
+ guard_no_exception(descr=...)
+ """, ignore_ops=['guard_not_invalidated'])
+
def test_cffi_call_guard_not_forced_fails(self):
# this is the test_pypy_c equivalent of
# rpython/jit/metainterp/test/test_fficall::test_guard_not_forced_fails
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
@@ -3,8 +3,7 @@
from rpython.rtyper.lltypesystem.lloperation import llop
from rpython.rlib import clibffi, jit
from rpython.rlib.rarithmetic import r_longlong, r_singlefloat
-
-BIG_ENDIAN = sys.byteorder == 'big'
+from rpython.rlib.unroll import unrolling_iterable
FFI_CIF = clibffi.FFI_CIFP.TO
FFI_TYPE = clibffi.FFI_TYPE_P.TO
@@ -114,8 +113,10 @@
reskind = types.getkind(cif_description.rtype)
if reskind == 'v':
jit_ffi_call_impl_void(cif_description, func_addr, exchange_buffer)
- elif reskind == 'i' or reskind == 'u':
- _do_ffi_call_int(cif_description, func_addr, exchange_buffer)
+ elif reskind == 'i':
+ _do_ffi_call_sint(cif_description, func_addr, exchange_buffer)
+ elif reskind == 'u':
+ _do_ffi_call_uint(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
@@ -132,21 +133,44 @@
jit_ffi_call_impl_any(cif_description, func_addr, exchange_buffer)
-def _do_ffi_call_int(cif_description, func_addr, exchange_buffer):
+_short_sint_types = unrolling_iterable([rffi.SIGNEDCHAR, rffi.SHORT, rffi.INT])
+_short_uint_types = unrolling_iterable([rffi.UCHAR, rffi.USHORT, rffi.UINT])
+
+def _do_ffi_call_sint(cif_description, func_addr, exchange_buffer):
result = jit_ffi_call_impl_int(cif_description, func_addr,
exchange_buffer)
- if BIG_ENDIAN:
- # Special case: we need to store an integer of 'c_size' bytes
- # only. To avoid type-specialization hell, we always store a
- # full Signed here, but by shifting it to the left on big-endian
- # we get the result that we want.
- size = rffi.getintfield(cif_description.rtype, 'c_size')
- if size < SIZE_OF_SIGNED:
- result <<= (SIZE_OF_SIGNED - size) * 8
- llop.raw_store(lltype.Void,
- llmemory.cast_ptr_to_adr(exchange_buffer),
- cif_description.exchange_result,
- result)
+ size = types.getsize(cif_description.rtype)
+ for TP in _short_sint_types: # short **signed** types
+ if size == rffi.sizeof(TP):
+ llop.raw_store(lltype.Void,
+ llmemory.cast_ptr_to_adr(exchange_buffer),
+ cif_description.exchange_result,
+ rffi.cast(TP, result))
+ break
+ else:
+ # default case: expect a full signed number
+ llop.raw_store(lltype.Void,
+ llmemory.cast_ptr_to_adr(exchange_buffer),
+ cif_description.exchange_result,
+ result)
+
+def _do_ffi_call_uint(cif_description, func_addr, exchange_buffer):
+ result = jit_ffi_call_impl_int(cif_description, func_addr,
+ exchange_buffer)
+ size = types.getsize(cif_description.rtype)
+ for TP in _short_uint_types: # short **unsigned** types
+ if size == rffi.sizeof(TP):
+ llop.raw_store(lltype.Void,
+ llmemory.cast_ptr_to_adr(exchange_buffer),
+ cif_description.exchange_result,
+ rffi.cast(TP, result))
+ break
+ else:
+ # default case: expect a full unsigned number
+ llop.raw_store(lltype.Void,
+ llmemory.cast_ptr_to_adr(exchange_buffer),
+ cif_description.exchange_result,
+ rffi.cast(lltype.Unsigned, result))
def _do_ffi_call_float(cif_description, func_addr, exchange_buffer):
# a separate function in case the backend doesn't support floats
@@ -284,6 +308,11 @@
@staticmethod
@jit.elidable
+ def getsize(ffi_type):
+ return rffi.getintfield(ffi_type, 'c_size')
+
+ @staticmethod
+ @jit.elidable
def is_struct(ffi_type):
return rffi.getintfield(ffi_type, 'c_type') == FFI_TYPE_STRUCT
More information about the pypy-commit
mailing list