[pypy-svn] pypy jitypes2: (david, antocuni)

antocuni commits-noreply at bitbucket.org
Thu Jan 20 19:52:08 CET 2011


Author: Antonio Cuni <anto.cuni at gmail.com>
Branch: jitypes2
Changeset: r41081:91741f4a1bf6
Date: 2011-01-20 17:51 +0100
http://bitbucket.org/pypy/pypy/changeset/91741f4a1bf6/

Log:	(david, antocuni)

	IN-PROGRESS: start to write the machinery to build specialized jit
	friendly versions of CFuncPtr that are used a set of conditions are
	met (e.g., as many args as argtypes, and no strange flags sets,
	etc.)

diff --git a/lib_pypy/_ctypes/function.py b/lib_pypy/_ctypes/function.py
--- a/lib_pypy/_ctypes/function.py
+++ b/lib_pypy/_ctypes/function.py
@@ -68,6 +68,10 @@
                     raise TypeError(
                         "item %d in _argtypes_ has no from_param method" % (
                             i + 1,))
+            #
+            # XXX tentative hack to make it jit-friendly
+            if len(argtypes) == 1:
+                self.__class__ = make_specialized_subclass(self.__class__)
             self._argtypes_ = list(argtypes)
     argtypes = property(_getargtypes, _setargtypes)
 
@@ -517,3 +521,61 @@
                 self._ptr.free()
                 self._ptr = None
             self._needs_free = False
+
+
+def make_specialized_subclass(CFuncPtr):
+    # XXX: we should probably cache the results
+
+    class CFuncPtr_1(CFuncPtr):
+
+        _num_args = 1
+
+        def _are_assumptions_met(self, args):
+            return (len(args) == self._num_args and
+                    self.callable is None and
+                    not self._com_index and
+                    self._argtypes_ is not None)
+
+        def __call__(self, *args):
+            if not self._are_assumptions_met(args):
+                # our assumptions are not met, rollback to the general, slow case
+                self.__class__ = CFuncPtr
+                return self(*args)
+
+            argtypes = self._argtypes_
+            thisarg = None
+            args = self._convert_args(argtypes, args)
+            argtypes = [type(arg) for arg in args]
+            newargs = self._unwrap_args(argtypes, args)
+
+            restype = self._restype_
+            funcptr = self._getfuncptr(argtypes, restype, thisarg)
+            if self._flags_ & _rawffi.FUNCFLAG_USE_ERRNO:
+                set_errno(_rawffi.get_errno())
+            if self._flags_ & _rawffi.FUNCFLAG_USE_LASTERROR:
+                set_last_error(_rawffi.get_last_error())
+            try:
+                result = funcptr(*newargs)
+                ## resbuffer = funcptr(*[arg._get_buffer_for_param()._buffer
+                ##                       for arg in args])
+            finally:
+                if self._flags_ & _rawffi.FUNCFLAG_USE_ERRNO:
+                    set_errno(_rawffi.get_errno())
+                if self._flags_ & _rawffi.FUNCFLAG_USE_LASTERROR:
+                    set_last_error(_rawffi.get_last_error())
+            result = self._build_result(restype, result, newargs)
+
+            # The 'errcheck' protocol
+            if self._errcheck_:
+                v = self._errcheck_(result, self, args)
+                # If the errcheck funtion failed, let it throw
+                # If the errcheck function returned callargs unchanged,
+                # continue normal processing.
+                # If the errcheck function returned something else,
+                # use that as result.
+                if v is not args:
+                    result = v
+
+            return result
+
+    return CFuncPtr_1


More information about the Pypy-commit mailing list