[pypy-svn] r69933 - in pypy/branch/virtual-forcing/pypy/rpython: . lltypesystem lltypesystem/test

arigo at codespeak.net arigo at codespeak.net
Sun Dec 6 20:04:30 CET 2009


Author: arigo
Date: Sun Dec  6 20:04:30 2009
New Revision: 69933

Modified:
   pypy/branch/virtual-forcing/pypy/rpython/lltypesystem/ll2ctypes.py
   pypy/branch/virtual-forcing/pypy/rpython/lltypesystem/test/test_ll2ctypes.py
   pypy/branch/virtual-forcing/pypy/rpython/rtyper.py
Log:
Tentative test and fix: remove ll2ctypes._parent_cache.
Instead, recontruct all the information about the real
type of an instance of OBJECT, purely in ctypes2lltype().
This is possible to do, as a small extension of code that
is already there.


Modified: pypy/branch/virtual-forcing/pypy/rpython/lltypesystem/ll2ctypes.py
==============================================================================
--- pypy/branch/virtual-forcing/pypy/rpython/lltypesystem/ll2ctypes.py	(original)
+++ pypy/branch/virtual-forcing/pypy/rpython/lltypesystem/ll2ctypes.py	Sun Dec  6 20:04:30 2009
@@ -30,7 +30,6 @@
 
 _ctypes_cache = {}
 _eci_cache = {}
-_parent_cache = {}
 
 def _setup_ctypes_cache():
     from pypy.rpython.lltypesystem import rffi
@@ -254,7 +253,6 @@
                 convert_struct(field_value, csubstruct)
                 subcontainer = getattr(container, field_name)
                 substorage = subcontainer._storage
-                update_parent_cache(substorage, subcontainer)
             elif field_name == STRUCT._arrayfld:    # inlined var-sized part
                 csubarray = getattr(cstruct, field_name)
                 convert_array(field_value, csubarray)
@@ -313,7 +311,6 @@
                 struct_storage = getattr(ctypes_storage, field_name)
                 struct_use_ctypes_storage(struct_container, struct_storage)
                 struct_container._setparentstructure(container, field_name)
-                update_parent_cache(ctypes_storage, struct_container)
             elif isinstance(FIELDTYPE, lltype.Array):
                 assert FIELDTYPE._hints.get('nolength', False) == False
                 arraycontainer = _array_of_known_length(FIELDTYPE)
@@ -633,8 +630,6 @@
                 raise NotImplementedError(T)
             container._ctypes_storage_was_allocated()
         storage = container._storage
-        if lltype.parentlink(container)[0] is not None:
-            update_parent_cache(storage, container)
         p = ctypes.pointer(storage)
         if index:
             p = ctypes.cast(p, ctypes.c_void_p)
@@ -673,26 +668,25 @@
         if not cobj:   # NULL pointer
             return lltype.nullptr(T.TO)
         if isinstance(T.TO, lltype.Struct):
+            REAL_TYPE = T.TO
             if T.TO._arrayfld is not None:
                 carray = getattr(cobj.contents, T.TO._arrayfld)
                 container = lltype._struct(T.TO, carray.length)
             else:
                 # special treatment of 'OBJECT' subclasses
-                if get_rtyper() and lltype._castdepth(T.TO, OBJECT) > 0:
-                    ctypes_object = get_ctypes_type(lltype.Ptr(OBJECT))
-                    as_obj = ctypes2lltype(lltype.Ptr(OBJECT),
-                                           ctypes.cast(cobj, ctypes_object))
-                    TObj = get_rtyper().get_type_for_typeptr(as_obj.typeptr)
-                    if TObj != T.TO:
-                        ctypes_instance = get_ctypes_type(lltype.Ptr(TObj))
-                        return lltype.cast_pointer(T,
-                            ctypes2lltype(lltype.Ptr(TObj),
-                                          ctypes.cast(cobj, ctypes_instance)))
-                container = lltype._struct(T.TO)
+                if get_rtyper() and lltype._castdepth(REAL_TYPE, OBJECT) >= 0:
+                    # figure out the real type of the object
+                    containerheader = lltype._struct(OBJECT)
+                    struct_use_ctypes_storage(containerheader, cobj.contents)
+                    REAL_TYPE = get_rtyper().get_type_for_typeptr(
+                        containerheader.typeptr)
+                    REAL_T = lltype.Ptr(REAL_TYPE)
+                    cobj = ctypes.cast(cobj, get_ctypes_type(REAL_T))
+                container = lltype._struct(REAL_TYPE)
             struct_use_ctypes_storage(container, cobj.contents)
-            addr = ctypes.addressof(cobj.contents)
-            if addr in _parent_cache:
-                setparentstructure(container, _parent_cache[addr])
+            if REAL_TYPE != T.TO:
+                p = container._as_ptr()
+                container = lltype.cast_pointer(T, p)._as_obj()
         elif isinstance(T.TO, lltype.Array):
             if T.TO._hints.get('nolength', False):
                 container = _array_of_unknown_length(T.TO)
@@ -1139,46 +1133,6 @@
         return hop.genop('cast_adr_to_int', [adr],
                          resulttype = lltype.Signed)
 
-# ------------------------------------------------------------
-
-def parentchain(container):
-    current = container
-    links = []
-    while True:
-        link = lltype.parentlink(current)
-        if link[0] is None:
-            try:
-                addr = ctypes.addressof(container._storage)
-                actual = _parent_cache[addr]
-                if len(links) < len(actual):
-                    return actual
-            except KeyError:
-                pass
-            return links
-        links.append(link)
-        current = link[0]
-
-def update_parent_cache(storage, container):
-    chain = parentchain(container)
-    addr = ctypes.addressof(storage)
-    try:
-        current = _parent_cache[addr]
-        if len(chain) > len(current):
-            _parent_cache[addr] = chain
-    except KeyError:
-        _parent_cache[addr] = chain
-
-def setparentstructure(container, chain):
-    TP = lltype.typeOf(container)
-    current = container
-    for i, elem in enumerate(chain):
-        if lltype.typeOf(elem[0]) == TP:
-            chain = chain[i + 1:]
-            break
-    for elem in chain:
-        current._setparentstructure(*elem)
-        current = elem[0]
-
 # ____________________________________________________________
 # errno
 

Modified: pypy/branch/virtual-forcing/pypy/rpython/lltypesystem/test/test_ll2ctypes.py
==============================================================================
--- pypy/branch/virtual-forcing/pypy/rpython/lltypesystem/test/test_ll2ctypes.py	(original)
+++ pypy/branch/virtual-forcing/pypy/rpython/lltypesystem/test/test_ll2ctypes.py	Sun Dec  6 20:04:30 2009
@@ -1109,17 +1109,18 @@
 
     def test_object_subclass(self):
         from pypy.rpython.lltypesystem import rclass
-        SCLASS = lltype.GcStruct('SCLASS',
-                                 ('parent', rclass.OBJECT),
-                                 ('x', lltype.Signed))
+        from pypy.rpython.annlowlevel import cast_instance_to_base_ptr
+        from pypy.rpython.annlowlevel import cast_base_ptr_to_instance
+        class S:
+            pass
         def f(n):
-            s = lltype.malloc(SCLASS)
+            s = S()
             s.x = n
-            gcref = lltype.cast_opaque_ptr(llmemory.GCREF, s)
-            as_num = rffi.cast(lltype.Signed, gcref)
-            gcref2 = rffi.cast(llmemory.GCREF, as_num)
-            t = lltype.cast_opaque_ptr(rclass.OBJECTPTR, gcref2)
-            u = lltype.cast_pointer(lltype.Ptr(SCLASS), t)
+            ls = cast_instance_to_base_ptr(s)
+            as_num = rffi.cast(lltype.Signed, ls)
+            # --- around this point, only 'as_num' is passed
+            t = rffi.cast(rclass.OBJECTPTR, as_num)
+            u = cast_base_ptr_to_instance(S, t)
             return u.x
         res = interpret(f, [123])
         assert res == 123

Modified: pypy/branch/virtual-forcing/pypy/rpython/rtyper.py
==============================================================================
--- pypy/branch/virtual-forcing/pypy/rpython/rtyper.py	(original)
+++ pypy/branch/virtual-forcing/pypy/rpython/rtyper.py	Sun Dec  6 20:04:30 2009
@@ -133,15 +133,22 @@
         return result
 
     def get_type_for_typeptr(self, typeptr):
+        search = typeptr._obj
         try:
-            return self.type_for_typeptr[typeptr._obj]
+            return self.type_for_typeptr[search]
         except KeyError:
-            # rehash the dictionary
+            # rehash the dictionary, and perform a non-dictionary scan
+            # for the case of ll2ctypes typeptr
+            found = None
             type_for_typeptr = {}
             for key, value in self.type_for_typeptr.items():
                 type_for_typeptr[key] = value
+                if key == search:
+                    found = value
             self.type_for_typeptr = type_for_typeptr
-            return self.type_for_typeptr[typeptr._obj]
+            if found is None:
+                raise KeyError(search)
+            return found
 
     def makekey(self, s_obj):
         return pair(self.type_system, s_obj).rtyper_makekey(self)



More information about the Pypy-commit mailing list