[pypy-commit] pypy reflex-support: refactoring for cleanup and to recover the speed lost for the void**/object** converters
wlav
noreply at buildbot.pypy.org
Tue May 8 06:07:17 CEST 2012
Author: Wim Lavrijsen <WLavrijsen at lbl.gov>
Branch: reflex-support
Changeset: r54954:1a776d4b2018
Date: 2012-05-07 17:12 -0700
http://bitbucket.org/pypy/pypy/changeset/1a776d4b2018/
Log: refactoring for cleanup and to recover the speed lost for the
void**/object** converters
diff --git a/pypy/module/cppyy/converter.py b/pypy/module/cppyy/converter.py
--- a/pypy/module/cppyy/converter.py
+++ b/pypy/module/cppyy/converter.py
@@ -42,6 +42,7 @@
class TypeConverter(object):
_immutable_ = True
libffitype = lltype.nullptr(clibffi.FFI_TYPE_P.TO)
+ uses_local = False
name = ""
@@ -178,6 +179,7 @@
class ConstRefNumericTypeConverterMixin(NumericTypeConverterMixin):
_mixin_ = True
_immutable_ = True
+ uses_local = True
def convert_argument_libffi(self, space, w_obj, argchain):
obj = self._unwrap_object(space, w_obj)
@@ -519,6 +521,7 @@
class VoidPtrPtrConverter(TypeConverter):
_immutable_ = True
+ uses_local = True
def convert_argument(self, space, w_obj, address, call_local):
r = rffi.cast(rffi.VOIDPP, call_local)
@@ -682,6 +685,7 @@
class InstancePtrPtrConverter(InstancePtrConverter):
_immutable_ = True
+ uses_local = True
def convert_argument(self, space, w_obj, address, call_local):
r = rffi.cast(rffi.VOIDPP, call_local)
diff --git a/pypy/module/cppyy/interp_cppyy.py b/pypy/module/cppyy/interp_cppyy.py
--- a/pypy/module/cppyy/interp_cppyy.py
+++ b/pypy/module/cppyy/interp_cppyy.py
@@ -112,55 +112,68 @@
""" A concrete function after overloading has been resolved """
_immutable_ = True
- def __init__(self, space, containing_scope, method_index, result_type, arg_defs, args_required):
+ def __init__(self, space, containing_scope, method_index, arg_defs, args_required):
self.space = space
self.scope = containing_scope
self.index = method_index
self.cppmethod = capi.c_get_method(self.scope, method_index)
self.arg_defs = arg_defs
self.args_required = args_required
- self.result_type = result_type
+ self.args_expected = len(arg_defs)
# Setup of the method dispatch's innards is done lazily, i.e. only when
# the method is actually used.
- self.arg_converters = None
+ self.converters = None
self.executor = None
self._libffifunc = None
- def _address_from_local_buffer(self, call_local, index):
- return lltype.direct_ptradd(rffi.cast(rffi.CCHARP, call_local), index*rffi.sizeof(rffi.VOIDP))
+ def _address_from_local_buffer(self, call_local, idx):
+ if not call_local:
+ return call_local
+ stride = rffi.sizeof(rffi.VOIDP)
+ loc_idx = lltype.direct_ptradd(rffi.cast(rffi.CCHARP, call_local), idx*stride)
+ return rffi.cast(rffi.VOIDP, loc_idx)
@jit.unroll_safe
def call(self, cppthis, args_w):
jit.promote(self)
assert lltype.typeOf(cppthis) == capi.C_OBJECT
+
+ # check number of given arguments against required (== total - defaults)
args_expected = len(self.arg_defs)
args_given = len(args_w)
if args_expected < args_given or args_given < self.args_required:
raise OperationError(self.space.w_TypeError,
self.space.wrap("wrong number of arguments"))
- if self.arg_converters is None:
+ # initial setup of converters, executors, and libffi (if available)
+ if self.converters is None:
self._setup(cppthis)
- call_local = lltype.malloc(rffi.CArray(rffi.VOIDP), len(args_w), flavor='raw')
+ # some calls, e.g. for ptr-ptr or reference need a local array to store data for
+ # the duration of the call
+ if [conv for conv in self.converters if conv.uses_local]:
+ call_local = rffi.lltype.malloc(rffi.VOIDP.TO, len(args_w), flavor='raw')
+ else:
+ call_local = lltype.nullptr(rffi.VOIDP.TO)
- if self._libffifunc:
+ try:
+ # attempt to call directly through ffi chain
+ if self._libffifunc:
+ try:
+ return self.do_fast_call(cppthis, args_w, call_local)
+ except FastCallNotPossible:
+ pass # can happen if converters or executor does not implement ffi
+
+ # ffi chain must have failed; using stub functions instead
+ args = self.prepare_arguments(args_w, call_local)
try:
- result = self.do_fast_call(cppthis, args_w, call_local)
+ return self.executor.execute(self.space, self.cppmethod, cppthis, len(args_w), args)
+ finally:
+ self.finalize_call(args, args_w, call_local)
+ finally:
+ if call_local:
lltype.free(call_local, flavor='raw')
- return result
- except FastCallNotPossible:
- pass # can happen if converters or executor does not implement ffi
- except:
- lltype.free(call_local, flavor='raw')
- raise
-
- args = self.prepare_arguments(args_w, call_local)
- try:
- return self.executor.execute(self.space, self.cppmethod, cppthis, len(args_w), args)
- finally:
- self.finalize_call(args, args_w, call_local)
@jit.unroll_safe
def do_fast_call(self, cppthis, args_w, call_local):
@@ -171,13 +184,13 @@
refbuffers = []
try:
for i in range(len(args_w)):
- conv = self.arg_converters[i]
+ conv = self.converters[i]
w_arg = args_w[i]
refbuf = conv.convert_argument_libffi(self.space, w_arg, argchain)
if refbuf:
refbuffers.append(refbuf)
for j in range(i+1, len(self.arg_defs)):
- conv = self.arg_converters[j]
+ conv = self.converters[j]
conv.default_argument_libffi(self.space, argchain)
return self.executor.execute_libffi(self.space, self._libffifunc, argchain)
finally:
@@ -185,9 +198,9 @@
lltype.free(refbuf, flavor='raw')
def _setup(self, cppthis):
- self.arg_converters = [converter.get_converter(self.space, arg_type, arg_dflt)
- for arg_type, arg_dflt in self.arg_defs]
- self.executor = executor.get_executor(self.space, self.result_type)
+ self.converters = [converter.get_converter(self.space, arg_type, arg_dflt)
+ for arg_type, arg_dflt in self.arg_defs]
+ self.executor = executor.get_executor(self.space, capi.c_method_result_type(self.scope, self.index))
# Each CPPMethod corresponds one-to-one to a C++ equivalent and cppthis
# has been offset to the matching class. Hence, the libffi pointer is
@@ -195,9 +208,8 @@
methgetter = capi.c_get_methptr_getter(self.scope, self.index)
if methgetter and cppthis: # methods only for now
funcptr = methgetter(rffi.cast(capi.C_OBJECT, cppthis))
- argtypes_libffi = [conv.libffitype for conv in self.arg_converters
- if conv.libffitype]
- if (len(argtypes_libffi) == len(self.arg_converters) and
+ argtypes_libffi = [conv.libffitype for conv in self.converters if conv.libffitype]
+ if (len(argtypes_libffi) == len(self.converters) and
self.executor.libffitype):
# add c++ this to the arguments
libffifunc = libffi.Func("XXX",
@@ -211,7 +223,7 @@
args = capi.c_allocate_function_args(len(args_w))
stride = capi.c_function_arg_sizeof()
for i in range(len(args_w)):
- conv = self.arg_converters[i]
+ conv = self.converters[i]
w_arg = args_w[i]
try:
arg_i = lltype.direct_ptradd(rffi.cast(rffi.CCHARP, args), i*stride)
@@ -220,12 +232,11 @@
except:
# fun :-(
for j in range(i):
- conv = self.arg_converters[j]
+ conv = self.converters[j]
arg_j = lltype.direct_ptradd(rffi.cast(rffi.CCHARP, args), j*stride)
loc_j = self._address_from_local_buffer(call_local, j)
conv.free_argument(rffi.cast(capi.C_OBJECT, arg_j), loc_j)
capi.c_deallocate_function_args(args)
- lltype.free(call_local, flavor='raw')
raise
return args
@@ -233,13 +244,12 @@
def finalize_call(self, args, args_w, call_local):
stride = capi.c_function_arg_sizeof()
for i in range(len(args_w)):
- conv = self.arg_converters[i]
+ conv = self.converters[i]
arg_i = lltype.direct_ptradd(rffi.cast(rffi.CCHARP, args), i*stride)
loc_i = self._address_from_local_buffer(call_local, i)
conv.finalize_call(self.space, args_w[i], loc_i)
conv.free_argument(rffi.cast(capi.C_OBJECT, arg_i), loc_i)
capi.c_deallocate_function_args(args)
- lltype.free(call_local, flavor='raw')
def signature(self):
return capi.c_method_signature(self.scope, self.index)
@@ -485,7 +495,6 @@
kind = "namespace"
def _make_cppfunction(self, method_index):
- result_type = capi.c_method_result_type(self, method_index)
num_args = capi.c_method_num_args(self, method_index)
args_required = capi.c_method_req_args(self, method_index)
arg_defs = []
@@ -493,7 +502,7 @@
arg_type = capi.c_method_arg_type(self, method_index, i)
arg_dflt = capi.c_method_arg_default(self, method_index, i)
arg_defs.append((arg_type, arg_dflt))
- return CPPFunction(self.space, self, method_index, result_type, arg_defs, args_required)
+ return CPPFunction(self.space, self, method_index, arg_defs, args_required)
def _make_datamember(self, dm_name, dm_idx):
type_name = capi.c_datamember_type(self, dm_idx)
@@ -551,7 +560,6 @@
kind = "class"
def _make_cppfunction(self, method_index):
- result_type = capi.c_method_result_type(self, method_index)
num_args = capi.c_method_num_args(self, method_index)
args_required = capi.c_method_req_args(self, method_index)
arg_defs = []
@@ -560,13 +568,12 @@
arg_dflt = capi.c_method_arg_default(self, method_index, i)
arg_defs.append((arg_type, arg_dflt))
if capi.c_is_constructor(self, method_index):
- result_type = "constructor"
cls = CPPConstructor
elif capi.c_is_staticmethod(self, method_index):
cls = CPPFunction
else:
cls = CPPMethod
- return cls(self.space, self, method_index, result_type, arg_defs, args_required)
+ return cls(self.space, self, method_index, arg_defs, args_required)
def _find_datamembers(self):
num_datamembers = capi.c_num_datamembers(self)
diff --git a/pypy/module/cppyy/src/cintcwrapper.cxx b/pypy/module/cppyy/src/cintcwrapper.cxx
--- a/pypy/module/cppyy/src/cintcwrapper.cxx
+++ b/pypy/module/cppyy/src/cintcwrapper.cxx
@@ -546,7 +546,14 @@
}
char* cppyy_method_result_type(cppyy_scope_t handle, int method_index) {
- TFunction* f = type_get_method(handle, method_index);
+ TFunction* f = 0;
+ TClassRef cr = type_from_handle(handle);
+ if (cr.GetClass()) {
+ if (cppyy_is_constructor(handle, method_index))
+ return cppstring_to_cstring("constructor");
+ f = (TFunction*)cr->GetListOfMethods()->At(method_index);
+ else
+ f = &g_globalfuncs[method_index];
return type_cppstring_to_cstring(f->GetReturnTypeName());
}
diff --git a/pypy/module/cppyy/src/reflexcwrapper.cxx b/pypy/module/cppyy/src/reflexcwrapper.cxx
--- a/pypy/module/cppyy/src/reflexcwrapper.cxx
+++ b/pypy/module/cppyy/src/reflexcwrapper.cxx
@@ -340,6 +340,8 @@
char* cppyy_method_result_type(cppyy_scope_t handle, int method_index) {
Reflex::Scope s = scope_from_handle(handle);
Reflex::Member m = s.FunctionMemberAt(method_index);
+ if (m.IsConstructor())
+ return cppstring_to_cstring("constructor");
Reflex::Type rt = m.TypeOf().ReturnType();
std::string name = rt.Name(Reflex::FINAL|Reflex::SCOPED|Reflex::QUALIFIED);
return cppstring_to_cstring(name);
More information about the pypy-commit
mailing list