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

Reply via email to