[pypy-commit] pypy default: Mostly no-op reorganization. It avoids promoting the whole W_FunctionWrapper
arigo
noreply at buildbot.pypy.org
Tue Jun 23 09:28:20 CEST 2015
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r78248:53cddb11ed7c
Date: 2015-06-23 09:25 +0200
http://bitbucket.org/pypy/pypy/changeset/53cddb11ed7c/
Log: Mostly no-op reorganization. It avoids promoting the whole
W_FunctionWrapper instance, and instead promotes only its
rawfunctype attribute.
diff --git a/pypy/module/_cffi_backend/lib_obj.py b/pypy/module/_cffi_backend/lib_obj.py
--- a/pypy/module/_cffi_backend/lib_obj.py
+++ b/pypy/module/_cffi_backend/lib_obj.py
@@ -60,12 +60,12 @@
self.ffi, self.ctx.c_types, getarg(g.c_type_op))
assert isinstance(rawfunctype, realize_c_type.W_RawFuncType)
#
- w_ct, locs = rawfunctype.unwrap_as_nostruct_fnptr(self.ffi)
+ rawfunctype.prepare_nostruct_fnptr(self.ffi)
#
ptr = rffi.cast(rffi.CCHARP, g.c_address)
assert ptr
- return W_FunctionWrapper(self.space, ptr, g.c_size_or_direct_fn, w_ct,
- locs, rawfunctype, fnname, self.libname)
+ return W_FunctionWrapper(self.space, ptr, g.c_size_or_direct_fn,
+ rawfunctype, fnname, self.libname)
@jit.elidable_promote()
def _get_attr_elidable(self, attr):
@@ -237,7 +237,8 @@
if isinstance(w_value, W_FunctionWrapper):
# '&func' returns a regular cdata pointer-to-function
if w_value.directfnptr:
- return W_CData(space, w_value.directfnptr, w_value.ctype)
+ ctype = w_value.rawfunctype.nostruct_ctype
+ return W_CData(space, w_value.directfnptr, ctype)
else:
return w_value # backward compatibility
#
diff --git a/pypy/module/_cffi_backend/realize_c_type.py b/pypy/module/_cffi_backend/realize_c_type.py
--- a/pypy/module/_cffi_backend/realize_c_type.py
+++ b/pypy/module/_cffi_backend/realize_c_type.py
@@ -1,4 +1,5 @@
import sys
+from rpython.rlib import jit
from rpython.rlib.rarithmetic import intmask
from rpython.rlib.objectmodel import specialize
from rpython.rtyper.lltypesystem import lltype, rffi
@@ -135,8 +136,12 @@
class W_RawFuncType(W_Root):
"""Temporary: represents a C function type (not a function pointer)"""
+
+ _immutable_fields_ = ['nostruct_ctype', 'nostruct_locs', 'nostruct_nargs']
_ctfuncptr = None
- _nostruct_ctfuncptr = (None, None)
+ nostruct_ctype = None
+ nostruct_locs = None
+ nostruct_nargs = 0
def __init__(self, opcodes, base_index):
self.opcodes = opcodes
@@ -168,14 +173,16 @@
assert self._ctfuncptr is not None
return self._ctfuncptr
- def unwrap_as_nostruct_fnptr(self, ffi):
- # tweaked version: instead of returning the ctfuncptr corresponding
- # exactly to the OP_FUNCTION ... OP_FUNCTION_END opcodes, return
- # another one in which the struct args are replaced with ptr-to-
- # struct, and a struct return value is replaced with a hidden first
- # arg of type ptr-to-struct. This is how recompiler.py produces
+ @jit.dont_look_inside
+ def prepare_nostruct_fnptr(self, ffi):
+ # tweaked version: instead of returning the ctfuncptr
+ # corresponding exactly to the OP_FUNCTION ... OP_FUNCTION_END
+ # opcodes, this builds in self.nostruct_ctype another one in
+ # which the struct args are replaced with ptr-to- struct, and
+ # a struct return value is replaced with a hidden first arg of
+ # type ptr-to-struct. This is how recompiler.py produces
# trampoline functions for PyPy.
- if self._nostruct_ctfuncptr[0] is None:
+ if self.nostruct_ctype is None:
fargs, fret, ellipsis = self._unpack(ffi)
# 'locs' will be a string of the same length as the final fargs,
# containing 'A' where a struct argument was detected, and 'R'
@@ -198,8 +205,10 @@
locs = None
else:
locs = ''.join(locs)
- self._nostruct_ctfuncptr = (ctfuncptr, locs)
- return self._nostruct_ctfuncptr
+ self.nostruct_ctype = ctfuncptr
+ self.nostruct_locs = locs
+ self.nostruct_nargs = len(ctfuncptr.fargs) - (locs is not None and
+ locs[0] == 'R')
def unexpected_fn_type(self, ffi):
fargs, fret, ellipsis = self._unpack(ffi)
diff --git a/pypy/module/_cffi_backend/wrapper.py b/pypy/module/_cffi_backend/wrapper.py
--- a/pypy/module/_cffi_backend/wrapper.py
+++ b/pypy/module/_cffi_backend/wrapper.py
@@ -25,8 +25,14 @@
_immutable_ = True
common_doc_str = 'direct call to the C function of the same name'
- def __init__(self, space, fnptr, directfnptr, ctype,
- locs, rawfunctype, fnname, modulename):
+ def __init__(self, space, fnptr, directfnptr,
+ rawfunctype, fnname, modulename):
+ # everything related to the type of the function is accessed
+ # as immutable attributes of the 'rawfunctype' object, which
+ # is a W_RawFuncType. This gives us an obvious thing to
+ # promote in order to do the call.
+ ctype = rawfunctype.nostruct_ctype
+ locs = rawfunctype.nostruct_locs
assert isinstance(ctype, W_CTypeFunc)
assert ctype.cif_descr is not None # not for '...' functions
assert locs is None or len(ctype.fargs) == len(locs)
@@ -34,84 +40,86 @@
self.space = space
self.fnptr = fnptr
self.directfnptr = directfnptr
- self.ctype = ctype
- self.locs = locs
self.rawfunctype = rawfunctype
self.fnname = fnname
self.modulename = modulename
- self.nargs_expected = len(ctype.fargs) - (locs is not None and
- locs[0] == 'R')
def typeof(self, ffi):
return self.rawfunctype.unwrap_as_fnptr(ffi)
- @jit.unroll_safe
- def _prepare(self, args_w, start_index):
- # replaces struct/union arguments with ptr-to-struct/union arguments
+ def descr_call(self, args_w):
space = self.space
- locs = self.locs
- fargs = self.ctype.fargs
- for i in range(start_index, len(locs)):
- if locs[i] != 'A':
- continue
- w_arg = args_w[i]
- farg = fargs[i] # <ptr to struct/union>
- assert isinstance(farg, W_CTypePtrOrArray)
- if isinstance(w_arg, W_CData) and w_arg.ctype is farg.ctitem:
- # fast way: we are given a W_CData "struct", so just make
- # a new W_CData "ptr-to-struct" which points to the same
- # raw memory. We use unsafe_escaping_ptr(), so we have to
- # make sure the original 'w_arg' stays alive; the easiest
- # is to build an instance of W_CDataPtrToStructOrUnion.
- w_arg = W_CDataPtrToStructOrUnion(
- space, w_arg.unsafe_escaping_ptr(), farg, w_arg)
- else:
- # slow way: build a new "ptr to struct" W_CData by calling
- # the equivalent of ffi.new()
- if space.is_w(w_arg, space.w_None):
- continue
- w_arg = farg.newp(w_arg)
- args_w[i] = w_arg
-
- def descr_call(self, args_w):
- self = jit.promote(self)
- if len(args_w) != self.nargs_expected:
- space = self.space
- if self.nargs_expected == 0:
+ rawfunctype = jit.promote(self.rawfunctype)
+ ctype = rawfunctype.nostruct_ctype
+ locs = rawfunctype.nostruct_locs
+ nargs_expected = rawfunctype.nostruct_nargs
+ #
+ if len(args_w) != nargs_expected:
+ if nargs_expected == 0:
raise oefmt(space.w_TypeError,
"%s() takes no arguments (%d given)",
self.fnname, len(args_w))
- elif self.nargs_expected == 1:
+ elif nargs_expected == 1:
raise oefmt(space.w_TypeError,
"%s() takes exactly one argument (%d given)",
self.fnname, len(args_w))
else:
raise oefmt(space.w_TypeError,
"%s() takes exactly %d arguments (%d given)",
- self.fnname, self.nargs_expected, len(args_w))
+ self.fnname, nargs_expected, len(args_w))
#
- if self.locs is not None:
+ if locs is not None:
# This case is if there are structs as arguments or return values.
# If the result we want to present to the user is "returns struct",
# then internally allocate the struct and pass a pointer to it as
# a first argument.
- if self.locs[0] == 'R':
- w_result_cdata = self.ctype.fargs[0].newp(self.space.w_None)
+ if locs[0] == 'R':
+ w_result_cdata = ctype.fargs[0].newp(space.w_None)
args_w = [w_result_cdata] + args_w
- self._prepare(args_w, 1)
- self.ctype._call(self.fnptr, args_w) # returns w_None
+ prepare_args(space, rawfunctype, args_w, 1)
+ #
+ ctype._call(self.fnptr, args_w) # returns w_None
+ #
assert isinstance(w_result_cdata, W_CDataPtrToStructOrUnion)
return w_result_cdata.structobj
else:
args_w = args_w[:]
- self._prepare(args_w, 0)
+ prepare_args(space, rawfunctype, args_w, 0)
#
- return self.ctype._call(self.fnptr, args_w)
+ return ctype._call(self.fnptr, args_w)
def descr_repr(self, space):
return space.wrap("<FFIFunctionWrapper for %s()>" % (self.fnname,))
+ at jit.unroll_safe
+def prepare_args(space, rawfunctype, args_w, start_index):
+ # replaces struct/union arguments with ptr-to-struct/union arguments
+ locs = rawfunctype.nostruct_locs
+ fargs = rawfunctype.nostruct_ctype.fargs
+ for i in range(start_index, len(locs)):
+ if locs[i] != 'A':
+ continue
+ w_arg = args_w[i]
+ farg = fargs[i] # <ptr to struct/union>
+ assert isinstance(farg, W_CTypePtrOrArray)
+ if isinstance(w_arg, W_CData) and w_arg.ctype is farg.ctitem:
+ # fast way: we are given a W_CData "struct", so just make
+ # a new W_CData "ptr-to-struct" which points to the same
+ # raw memory. We use unsafe_escaping_ptr(), so we have to
+ # make sure the original 'w_arg' stays alive; the easiest
+ # is to build an instance of W_CDataPtrToStructOrUnion.
+ w_arg = W_CDataPtrToStructOrUnion(
+ space, w_arg.unsafe_escaping_ptr(), farg, w_arg)
+ else:
+ # slow way: build a new "ptr to struct" W_CData by calling
+ # the equivalent of ffi.new()
+ if space.is_w(w_arg, space.w_None):
+ continue
+ w_arg = farg.newp(w_arg)
+ args_w[i] = w_arg
+
+
W_FunctionWrapper.typedef = TypeDef(
'FFIFunctionWrapper',
__repr__ = interp2app(W_FunctionWrapper.descr_repr),
More information about the pypy-commit
mailing list