Author: Wim Lavrijsen <[email protected]>
Branch: reflex-support
Changeset: r52330:985018b0e02c
Date: 2012-02-09 12:14 -0800
http://bitbucket.org/pypy/pypy/changeset/985018b0e02c/
Log: o) factored out direct_ptradd o) optimization to only calculate
offsets if necessary (w/o guards)
diff --git a/pypy/module/cppyy/capi/__init__.py
b/pypy/module/cppyy/capi/__init__.py
--- a/pypy/module/cppyy/capi/__init__.py
+++ b/pypy/module/cppyy/capi/__init__.py
@@ -15,6 +15,13 @@
C_METHPTRGETTER = lltype.FuncType([C_OBJECT], rffi.VOIDP)
C_METHPTRGETTER_PTR = lltype.Ptr(C_METHPTRGETTER)
+def direct_ptradd(ptr, offset):
+ offset = rffi.cast(rffi.SIZE_T, offset)
+ jit.promote(offset)
+ assert lltype.typeOf(ptr) == C_OBJECT
+ address = rffi.cast(rffi.CCHARP, ptr)
+ return rffi.cast(C_OBJECT, lltype.direct_ptradd(address, offset))
+
c_load_dictionary = backend.c_load_dictionary
c_get_typehandle = rffi.llexternal(
@@ -48,6 +55,10 @@
[C_TYPEHANDLE], rffi.CCHARP,
compilation_info=backend.eci)
+c_has_complex_hierarchy = rffi.llexternal(
+ "cppyy_has_complex_hierarchy",
+ [C_TYPEHANDLE], rffi.INT,
+ compilation_info=backend.eci)
c_num_bases = rffi.llexternal(
"cppyy_num_bases",
[C_TYPEHANDLE], rffi.INT,
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
@@ -19,11 +19,6 @@
return cppinstance.rawobject
return capi.C_NULL_OBJECT
-def _direct_ptradd(ptr, offset): # TODO: factor out with interp_cppyy.py
- assert lltype.typeOf(ptr) == capi.C_OBJECT
- address = rffi.cast(rffi.CCHARP, ptr)
- return rffi.cast(capi.C_OBJECT, lltype.direct_ptradd(address, offset))
-
class TypeConverter(object):
_immutable_ = True
@@ -38,7 +33,7 @@
rawobject = get_rawobject(space, w_obj)
assert lltype.typeOf(rawobject) == capi.C_OBJECT
if rawobject:
- fieldptr = _direct_ptradd(rawobject, offset)
+ fieldptr = capi.direct_ptradd(rawobject, offset)
else:
fieldptr = rffi.cast(capi.C_OBJECT, offset)
return fieldptr
@@ -129,7 +124,7 @@
def to_memory(self, space, w_obj, w_value, offset):
# copy only the pointer value
rawobject = get_rawobject(space, w_obj)
- byteptr = rffi.cast(rffi.CCHARPP, _direct_ptradd(rawobject, offset))
+ byteptr = rffi.cast(rffi.CCHARPP, capi.direct_ptradd(rawobject,
offset))
buf = space.buffer_w(w_value)
try:
byteptr[0] = buf.get_raw_address()
@@ -174,7 +169,7 @@
x = rffi.cast(self.rffiptype, address)
x[0] = self._unwrap_object(space, w_obj)
typecode = rffi.cast(rffi.CCHARP,
- _direct_ptradd(address, capi.c_function_arg_typeoffset()))
+ capi.direct_ptradd(address, capi.c_function_arg_typeoffset()))
typecode[0] = self.typecode
@@ -371,7 +366,7 @@
arg = space.str_w(w_obj)
x[0] = rffi.cast(rffi.LONG, rffi.str2charp(arg))
typecode = rffi.cast(rffi.CCHARP,
- _direct_ptradd(address, capi.c_function_arg_typeoffset()))
+ capi.direct_ptradd(address, capi.c_function_arg_typeoffset()))
typecode[0] = 'a'
def from_memory(self, space, w_obj, w_type, offset):
@@ -390,7 +385,7 @@
x = rffi.cast(rffi.VOIDPP, address)
x[0] = rffi.cast(rffi.VOIDP, get_rawobject(space, w_obj))
typecode = rffi.cast(rffi.CCHARP,
- _direct_ptradd(address, capi.c_function_arg_typeoffset()))
+ capi.direct_ptradd(address, capi.c_function_arg_typeoffset()))
typecode[0] = 'a'
def convert_argument_libffi(self, space, w_obj, argchain):
@@ -404,7 +399,7 @@
x = rffi.cast(rffi.VOIDPP, address)
x[0] = rffi.cast(rffi.VOIDP, get_rawobject(space, w_obj))
typecode = rffi.cast(rffi.CCHARP,
- _direct_ptradd(address, capi.c_function_arg_typeoffset()))
+ capi.direct_ptradd(address, capi.c_function_arg_typeoffset()))
typecode[0] = 'p'
@@ -415,7 +410,7 @@
x = rffi.cast(rffi.VOIDPP, address)
x[0] = rffi.cast(rffi.VOIDP, get_rawobject(space, w_obj))
typecode = rffi.cast(rffi.CCHARP,
- _direct_ptradd(address, capi.c_function_arg_typeoffset()))
+ capi.direct_ptradd(address, capi.c_function_arg_typeoffset()))
typecode[0] = 'r'
@@ -518,7 +513,7 @@
if capi.c_is_subtype(obj.cppclass.handle, self.cpptype.handle):
offset = capi.c_base_offset(
obj.cppclass.handle, self.cpptype.handle, obj.rawobject)
- obj_address = _direct_ptradd(obj.rawobject, offset)
+ obj_address = capi.direct_ptradd(obj.rawobject, offset)
return rffi.cast(capi.C_OBJECT, obj_address)
raise OperationError(space.w_TypeError,
space.wrap("cannot pass %s as %s" % (
@@ -530,7 +525,7 @@
x[0] = rffi.cast(rffi.VOIDP, self._unwrap_object(space, w_obj))
address = rffi.cast(capi.C_OBJECT, address)
typecode = rffi.cast(rffi.CCHARP,
- _direct_ptradd(address, capi.c_function_arg_typeoffset()))
+ capi.direct_ptradd(address, capi.c_function_arg_typeoffset()))
typecode[0] = 'o'
def convert_argument_libffi(self, space, w_obj, argchain):
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
@@ -43,6 +43,7 @@
/* type/class reflection information
-------------------------------------- */
char* cppyy_final_name(cppyy_typehandle_t handle);
+ int cppyy_has_complex_hierarchy(cppyy_typehandle_t handle);
int cppyy_num_bases(cppyy_typehandle_t handle);
char* cppyy_base_name(cppyy_typehandle_t handle, int base_index);
int cppyy_is_subtype(cppyy_typehandle_t dh, cppyy_typehandle_t bh);
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
@@ -16,10 +16,6 @@
class FastCallNotPossible(Exception):
pass
-def _direct_ptradd(ptr, offset): # TODO: factor out with convert.py
- assert lltype.typeOf(ptr) == capi.C_OBJECT
- address = rffi.cast(rffi.CCHARP, ptr)
- return rffi.cast(capi.C_OBJECT, lltype.direct_ptradd(address, offset))
@unwrap_spec(name=str)
def load_dictionary(space, name):
@@ -48,8 +44,10 @@
final_name = capi.charp2str_free(capi.c_final_name(handle))
if capi.c_is_namespace(handle):
cpptype = W_CPPNamespace(space, final_name, handle)
- else:
- cpptype = W_CPPType(space, final_name, handle)
+ elif capi.c_has_complex_hierarchy(handle):
+ cpptype = W_ComplexCPPType(space, final_name, handle)
+ else:
+ cpptype = W_CPPType(space, final_name, handle)
state.cpptype_cache[name] = cpptype
cpptype._find_methods()
cpptype._find_data_members()
@@ -249,22 +247,14 @@
def get_returntype(self):
return self.space.wrap(self.functions[0].executor.name)
- @jit.elidable_promote()
- def _get_cppthis(self, cppinstance):
- if cppinstance is not None:
- cppinstance._nullcheck()
- offset = capi.c_base_offset(
- cppinstance.cppclass.handle, self.scope_handle,
cppinstance.rawobject)
- cppthis = _direct_ptradd(cppinstance.rawobject, offset)
- assert lltype.typeOf(cppthis) == capi.C_OBJECT
- else:
- cppthis = capi.C_NULL_OBJECT
- return cppthis
-
@jit.unroll_safe
def call(self, w_cppinstance, w_type, args_w):
cppinstance = self.space.interp_w(W_CPPInstance, w_cppinstance,
can_be_None=True)
- cppthis = self._get_cppthis(cppinstance)
+ if cppinstance is not None:
+ cppinstance._nullcheck()
+ cppthis = cppinstance.cppclass.get_cppthis(cppinstance,
self.scope_handle)
+ else:
+ cppthis = capi.C_NULL_OBJECT
assert lltype.typeOf(cppthis) == capi.C_OBJECT
space = self.space
@@ -491,6 +481,10 @@
data_member = W_CPPDataMember(self.space, self.handle, type_name,
offset, is_static)
self.data_members[data_member_name] = data_member
+ @jit.elidable_promote()
+ def get_cppthis(self, cppinstance, scope_handle):
+ return cppinstance.rawobject
+
def is_namespace(self):
return self.space.w_False
@@ -515,6 +509,26 @@
W_CPPType.typedef.acceptable_as_base_class = False
+class W_ComplexCPPType(W_CPPType):
+ @jit.elidable_promote()
+ def get_cppthis(self, cppinstance, scope_handle):
+ offset = capi.c_base_offset(
+ cppinstance.cppclass.handle, scope_handle, cppinstance.rawobject)
+ return capi.direct_ptradd(cppinstance.rawobject, offset)
+
+W_ComplexCPPType.typedef = TypeDef(
+ 'ComplexCPPType',
+ type_name = interp_attrproperty('name', W_CPPType),
+ get_base_names = interp2app(W_ComplexCPPType.get_base_names,
unwrap_spec=['self']),
+ get_method_names = interp2app(W_ComplexCPPType.get_method_names,
unwrap_spec=['self']),
+ get_overload = interp2app(W_ComplexCPPType.get_overload,
unwrap_spec=['self', str]),
+ get_data_member_names = interp2app(W_ComplexCPPType.get_data_member_names,
unwrap_spec=['self']),
+ get_data_member = interp2app(W_ComplexCPPType.get_data_member,
unwrap_spec=['self', str]),
+ is_namespace = interp2app(W_ComplexCPPType.is_namespace,
unwrap_spec=['self']),
+)
+W_ComplexCPPType.typedef.acceptable_as_base_class = False
+
+
class W_CPPTemplateType(Wrappable):
_immutable_fields_ = ["name", "handle"]
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
@@ -300,6 +300,12 @@
return cppstring_to_cstring(cr.GetClassName());
}
+int cppyy_has_complex_hierarchy(cppyy_typehandle_t handle) {
+// as long as no fast path is supported for CINT, calculating offsets (which
+// are cached by the JIT) is not going to hurt
+ return 1;
+}
+
int cppyy_num_bases(cppyy_typehandle_t handle) {
TClassRef cr = type_from_handle(handle);
if (cr.GetClass() && cr->GetListOfBases() != 0)
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
@@ -9,7 +9,6 @@
#include "Reflex/PropertyList.h"
#include "Reflex/TypeTemplate.h"
-#include <iostream>
#include <string>
#include <utility>
#include <vector>
@@ -208,6 +207,30 @@
return cppstring_to_cstring(name);
}
+static int cppyy_has_complex_hierarchy(const Reflex::Type& t) {
+ int is_complex = 1;
+
+ size_t nbases = t.BaseSize();
+ if (1 < nbases)
+ is_complex = 1;
+ else if (nbases == 0)
+ is_complex = 0;
+ else { // one base class only
+ Reflex::Base b = t.BaseAt(0);
+ if (b.IsVirtual())
+ is_complex = 1; // TODO: verify; can be complex, need not be.
+ else
+ is_complex = cppyy_has_complex_hierarchy(t.BaseAt(0).ToType());
+ }
+
+ return is_complex;
+}
+
+int cppyy_has_complex_hierarchy(cppyy_typehandle_t handle) {
+ Reflex::Type t = type_from_handle(handle);
+ return cppyy_has_complex_hierarchy(t);
+}
+
int cppyy_num_bases(cppyy_typehandle_t handle) {
Reflex::Type t = type_from_handle(handle);
return t.BaseSize();
diff --git a/pypy/module/cppyy/test/test_zjit.py
b/pypy/module/cppyy/test/test_zjit.py
--- a/pypy/module/cppyy/test/test_zjit.py
+++ b/pypy/module/cppyy/test/test_zjit.py
@@ -32,7 +32,7 @@
def _opaque_direct_ptradd(ptr, offset):
address = rffi.cast(rffi.CCHARP, ptr)
return rffi.cast(capi.C_OBJECT, lltype.direct_ptradd(address, offset))
-interp_cppyy._direct_ptradd = _opaque_direct_ptradd
+capi.direct_ptradd = _opaque_direct_ptradd
class FakeUserDelAction(object):
def __init__(self, space):
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit