[pypy-commit] pypy ffistruct: move the code to get/set arbitrary struct fields to rlib.libffi. Eventually, these two functions will be recognized and optimized by the JIT

antocuni noreply at buildbot.pypy.org
Wed Sep 7 14:55:54 CEST 2011


Author: Antonio Cuni <anto.cuni at gmail.com>
Branch: ffistruct
Changeset: r47134:750b3e0a7cf1
Date: 2011-09-07 14:53 +0200
http://bitbucket.org/pypy/pypy/changeset/750b3e0a7cf1/

Log:	move the code to get/set arbitrary struct fields to rlib.libffi.
	Eventually, these two functions will be recognized and optimized by
	the JIT

diff --git a/pypy/module/_ffi/interp_struct.py b/pypy/module/_ffi/interp_struct.py
--- a/pypy/module/_ffi/interp_struct.py
+++ b/pypy/module/_ffi/interp_struct.py
@@ -1,5 +1,6 @@
 from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.rlib import clibffi
+from pypy.rlib import libffi
 from pypy.interpreter.baseobjspace import Wrappable
 from pypy.interpreter.typedef import TypeDef, interp_attrproperty
 from pypy.interpreter.gateway import interp2app, unwrap_spec
@@ -104,10 +105,7 @@
         assert w_ffitype is app_types.slong # XXX: handle all cases
         FIELD_TYPE  = rffi.LONG
         #
-        addr = rffi.ptradd(self.rawmem, offset)
-        PTR_FIELD = lltype.Ptr(rffi.CArray(FIELD_TYPE))
-        value = rffi.cast(PTR_FIELD, addr)[0]
-        #
+        value = libffi.struct_getfield(FIELD_TYPE, self.rawmem, offset)
         return space.wrap(value)
 
     @unwrap_spec(name=str)
@@ -117,9 +115,7 @@
         FIELD_TYPE  = rffi.LONG
         value = space.int_w(w_value)
         #
-        addr = rffi.ptradd(self.rawmem, offset)
-        PTR_FIELD = lltype.Ptr(rffi.CArray(FIELD_TYPE))
-        rffi.cast(PTR_FIELD, addr)[0] = value
+        libffi.struct_setfield(FIELD_TYPE, self.rawmem, offset, value)
 
 
 
diff --git a/pypy/rlib/libffi.py b/pypy/rlib/libffi.py
--- a/pypy/rlib/libffi.py
+++ b/pypy/rlib/libffi.py
@@ -410,3 +410,29 @@
 
     def getaddressindll(self, name):
         return dlsym(self.lib, name)
+
+
+# ======================================================================
+
+ at jit.dont_look_inside
+ at specialize.arg(0)
+def struct_getfield(TYPE, addr, offset):
+    """
+    Read the field of type TYPE at addr+offset.
+    addr is of type rffi.VOIDP, offset is an int.
+    """
+    addr = rffi.ptradd(addr, offset)
+    PTR_FIELD = lltype.Ptr(rffi.CArray(TYPE))
+    return rffi.cast(PTR_FIELD, addr)[0]
+
+
+ at jit.dont_look_inside
+ at specialize.arg(0)
+def struct_setfield(TYPE, addr, offset, value):
+    """
+    Read the field of type TYPE at addr+offset.
+    addr is of type rffi.VOIDP, offset is an int.
+    """
+    addr = rffi.ptradd(addr, offset)
+    PTR_FIELD = lltype.Ptr(rffi.CArray(TYPE))
+    rffi.cast(PTR_FIELD, addr)[0] = value
diff --git a/pypy/rlib/test/test_libffi.py b/pypy/rlib/test/test_libffi.py
--- a/pypy/rlib/test/test_libffi.py
+++ b/pypy/rlib/test/test_libffi.py
@@ -5,7 +5,7 @@
 from pypy.rlib.rarithmetic import r_singlefloat, r_longlong, r_ulonglong
 from pypy.rlib.test.test_clibffi import BaseFfiTest, get_libm_name, make_struct_ffitype_e
 from pypy.rlib.libffi import CDLL, Func, get_libc_name, ArgChain, types
-from pypy.rlib.libffi import IS_32_BIT
+from pypy.rlib.libffi import IS_32_BIT, struct_getfield, struct_setfield
 
 class TestLibffiMisc(BaseFfiTest):
 
@@ -52,6 +52,24 @@
         del lib
         assert not ALLOCATED
 
+    def test_struct_fields(self):
+        longsize = 4 if IS_32_BIT else 8
+        POINT = lltype.Struct('POINT', ('x', rffi.LONG), ('y', rffi.LONG))
+        p = lltype.malloc(POINT, flavor='raw')
+        p.x = 42
+        p.y = 43
+        addr = rffi.cast(rffi.VOIDP, p)
+        assert struct_getfield(rffi.LONG, addr, 0) == 42
+        assert struct_getfield(rffi.LONG, addr, longsize) == 43
+        #
+        struct_setfield(rffi.LONG, addr, 0, 123)
+        struct_setfield(rffi.LONG, addr, longsize, 321)
+        assert p.x == 123
+        assert p.y == 321
+        #
+        lltype.free(p, flavor='raw')
+        
+
 class TestLibffiCall(BaseFfiTest):
     """
     Test various kind of calls through libffi.


More information about the pypy-commit mailing list