[pypy-commit] pypy cppyy-packaging: restore std::vector speedups
wlav
pypy.commits at gmail.com
Sat Jul 28 05:01:42 EDT 2018
Author: Wim Lavrijsen <WLavrijsen at lbl.gov>
Branch: cppyy-packaging
Changeset: r94910:422177baf4ea
Date: 2018-07-28 01:15 -0700
http://bitbucket.org/pypy/pypy/changeset/422177baf4ea/
Log: restore std::vector speedups
diff --git a/pypy/module/_cppyy/capi/loadable_capi.py b/pypy/module/_cppyy/capi/loadable_capi.py
--- a/pypy/module/_cppyy/capi/loadable_capi.py
+++ b/pypy/module/_cppyy/capi/loadable_capi.py
@@ -1,13 +1,18 @@
import os
+
from rpython.rtyper.lltypesystem import rffi, lltype
from rpython.rlib.rarithmetic import intmask
from rpython.rlib import jit, jit_libffi, libffi, rdynload, objectmodel
from rpython.rlib.rarithmetic import r_singlefloat
from rpython.tool import leakfinder
-from pypy.interpreter.gateway import interp2app
-from pypy.interpreter.error import oefmt
+from pypy.interpreter.error import OperationError, oefmt
+from pypy.interpreter.argument import Arguments
+from pypy.interpreter.gateway import interp2app, interpindirect2app
+from pypy.interpreter.typedef import TypeDef
+from pypy.objspace.std.iterobject import W_AbstractSeqIterObject
+from pypy.module._rawffi.array import W_ArrayInstance
from pypy.module._cffi_backend import ctypefunc, ctypeprim, cdataobj, misc
from pypy.module._cffi_backend import newtype
from pypy.module._cppyy import ffitypes
@@ -274,8 +279,9 @@
'stdstring2charp' : ([c_object, c_voidp], c_ccharp),
'stdstring2stdstring' : ([c_object], c_object),
- 'stdvector_valuetype' : ([c_ccharp], c_ccharp),
- 'stdvector_valuesize' : ([c_ccharp], c_size_t),
+ 'longdouble2double' : ([c_voidp], c_double),
+ 'double2longdouble' : ([c_double, c_voidp], c_void),
+
'vectorbool_getitem' : ([c_object, c_int], c_int),
'vectorbool_setitem' : ([c_object, c_int, c_int], c_void),
}
@@ -658,13 +664,6 @@
def c_stdstring2stdstring(space, cppobject):
return _cdata_to_cobject(space, call_capi(space, 'stdstring2stdstring', [_ArgH(cppobject)]))
-def c_stdvector_valuetype(space, pystr):
- return charp2str_free(space, call_capi(space, 'stdvector_valuetype', [_ArgS(pystr)]))
-
-def c_stdvector_valuetype(space, pystr):
- return charp2str_free(space, call_capi(space, 'stdvector_valuetype', [_ArgS(pystr)]))
-def c_stdvector_valuesize(space, pystr):
- return _cdata_to_size_t(space, call_capi(space, 'stdvector_valuesize', [_ArgS(pystr)]))
def c_vectorbool_getitem(space, vbool, idx):
return call_capi(space, 'vectorbool_getitem', [_ArgH(vbool), _ArgL(idx)])
def c_vectorbool_setitem(space, vbool, idx, value):
@@ -702,6 +701,52 @@
idx = vbool_getindex(space, w_self, w_idx)
c_vectorbool_setitem(space, vbool._rawobject, idx, int(space.is_true(w_value)))
+class W_STLVectorIter(W_AbstractSeqIterObject):
+ # w_seq and index are in base class
+ _immutable_fields_ = ['converter', 'data', 'len', 'stride']
+
+ def __init__(self, space, w_vector):
+ W_AbstractSeqIterObject.__init__(self, w_vector)
+ # TODO: this should live in rpythonize.py or something so that the
+ # imports can move to the top w/o getting circles
+ from pypy.module._cppyy import interp_cppyy
+ assert isinstance(w_vector, interp_cppyy.W_CPPInstance)
+ vector = space.interp_w(interp_cppyy.W_CPPInstance, w_vector)
+
+ v_type = c_resolve_name(space, vector.clsdecl.name+'::value_type')
+ v_size = c_size_of_type(space, v_type)
+
+ if not v_type or not v_size:
+ raise NotImplementedError # fallback on getitem
+
+ from pypy.module._cppyy import converter
+ self.converter = converter.get_converter(space, v_type, '')
+
+ # this 'data' is from the decl, so not the pythonized data from pythonify.py
+ w_arr = space.call_obj_args(vector.clsdecl.get_overload('data'), w_vector, Arguments(space, []))
+ arr = space.interp_w(W_ArrayInstance, w_arr, can_be_None=True)
+ if not arr:
+ raise OperationError(space.w_StopIteration, space.w_None)
+
+ self.data = rffi.cast(rffi.CCHARP, space.uint_w(arr.getbuffer(space)))
+ self.len = space.uint_w(space.call_obj_args(vector.clsdecl.get_overload('size'), w_vector, Arguments(space, [])))
+ self.stride = v_size
+
+ def descr_next(self, space):
+ if self.w_seq is None:
+ raise OperationError(space.w_StopIteration, space.w_None)
+ if self.len <= self.index:
+ self.w_seq = None
+ raise OperationError(space.w_StopIteration, space.w_None)
+ offset = lltype.direct_ptradd(self.data, rffi.cast(rffi.SIZE_T, self.index*self.stride))
+ w_item = self.converter.from_memory(space, space.w_None, rffi.cast(rffi.LONG, offset))
+ self.index += 1
+ return w_item
+
+def stdvector_iter(space, w_self):
+ return W_STLVectorIter(space, w_self)
+
+
# setup pythonizations for later use at run-time
_pythonizations = {}
def register_pythonizations(space):
@@ -712,6 +757,9 @@
### std::string
stdstring_c_str,
+ ### std::vector
+ stdvector_iter,
+
### std::vector<bool>
vectorbool_getitem,
vectorbool_setitem,
@@ -730,6 +778,9 @@
_method_alias(space, w_pycppclass, "_cppyy_as_builtin", "c_str")
_method_alias(space, w_pycppclass, "__str__", "c_str")
- if name == "std::vector<bool>":
+ if name.find("std::vector<bool", 0, 16) == 0:
space.setattr(w_pycppclass, space.newtext("__getitem__"), _pythonizations["vectorbool_getitem"])
space.setattr(w_pycppclass, space.newtext("__setitem__"), _pythonizations["vectorbool_setitem"])
+
+ elif name.find("std::vector", 0, 11) == 0:
+ space.setattr(w_pycppclass, space.newtext("__iter__"), _pythonizations["stdvector_iter"])
diff --git a/pypy/module/_cppyy/include/capi.h b/pypy/module/_cppyy/include/capi.h
--- a/pypy/module/_cppyy/include/capi.h
+++ b/pypy/module/_cppyy/include/capi.h
@@ -220,10 +220,6 @@
cppyy_object_t cppyy_stdstring2stdstring(cppyy_object_t ptr);
RPY_EXTERN
- const char* cppyy_stdvector_valuetype(const char* clname);
- RPY_EXTERN
- size_t cppyy_stdvector_valuesize(const char* clname);
- RPY_EXTERN
int cppyy_vectorbool_getitem(cppyy_object_t ptr, int idx);
RPY_EXTERN
void cppyy_vectorbool_setitem(cppyy_object_t ptr, int idx, int value);
diff --git a/pypy/module/_cppyy/pythonify.py b/pypy/module/_cppyy/pythonify.py
--- a/pypy/module/_cppyy/pythonify.py
+++ b/pypy/module/_cppyy/pythonify.py
@@ -435,9 +435,8 @@
# map begin()/end() protocol to iter protocol on STL(-like) classes, but
# not on vector, which is pythonized in the capi (interp-level; there is
# also the fallback on the indexed __getitem__, but that is slower)
-# TODO: if not (0 <= name.find('vector') <= 5):
add_checked_item = False
- if not (0 <= name.find('vector<bool') <= 5):
+ if name.find('std::vector', 0, 11) != 0:
if ('begin' in pyclass.__dict__ and 'end' in pyclass.__dict__):
if _cppyy._scope_byname(name+'::iterator') or \
_cppyy._scope_byname(name+'::const_iterator'):
@@ -454,7 +453,7 @@
add_checked_item = True
# add python collection based initializer
- if 0 <= name.find('vector') <= 5:
+ if name.find('std::vector', 0, 11) == 0:
pyclass.__real_init__ = pyclass.__init__
def vector_init(self, *args):
if len(args) == 1 and isinstance(args[0], (tuple, list)):
@@ -478,8 +477,8 @@
# TODO: must be a simpler way to check (or at least hook these to a namespace
# std specific pythonizor)
- if add_checked_item or 0 <= name.find('vector') <= 5 or \
- 0 <= name.find('array') <= 5 or 0 <= name.find('deque') <= 5:
+ if add_checked_item or name.find('std::vector', 0, 11) == 0 or \
+ name.find('std::array', 0, 11) == 0 or name.find('std::deque', 0, 10) == 0:
# combine __getitem__ and __len__ to make a pythonized __getitem__
if '__getitem__' in pyclass.__dict__ and '__len__' in pyclass.__dict__:
pyclass._getitem__unchecked = pyclass.__getitem__
More information about the pypy-commit
mailing list