[pypy-svn] r36120 - in pypy/dist/pypy: rlib/rctypes rlib/rctypes/test rpython rpython/lltypesystem rpython/lltypesystem/test rpython/memory rpython/memory/gctransform rpython/memory/gctransform/test translator/c translator/llvm

arigo at codespeak.net arigo at codespeak.net
Wed Jan 3 16:26:44 CET 2007


Author: arigo
Date: Wed Jan  3 16:26:37 2007
New Revision: 36120

Modified:
   pypy/dist/pypy/rlib/rctypes/rctypesobject.py
   pypy/dist/pypy/rlib/rctypes/test/test_rctypesobject.py
   pypy/dist/pypy/rpython/llinterp.py
   pypy/dist/pypy/rpython/lltypesystem/llmemory.py
   pypy/dist/pypy/rpython/lltypesystem/lltype.py
   pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py
   pypy/dist/pypy/rpython/memory/gcheader.py
   pypy/dist/pypy/rpython/memory/gctransform/framework.py
   pypy/dist/pypy/rpython/memory/gctransform/test/test_framework.py
   pypy/dist/pypy/translator/c/database.py
   pypy/dist/pypy/translator/c/primitive.py
   pypy/dist/pypy/translator/llvm/database.py
Log:
Simplification of llmemory, triggered by the fact that two addresses
would compare as different if they were obtained in different ways,
even if they pointed to the same final object.

The 'offset' field of fakeaddress is gone, and 'ob' is renamed to 'ptr'.
It's always just a pointer.  With the new stuff in lltype like
direct_fieldptr() we can take pointers to fields, or array items, so no
need for anything more.

Hack a bit for arenas and address-of-length-of-array.

A new test in rctypesobject that triggered this whole thing,
and implementation of recursive data structures.

llvm/database.py updated but not tested (will do so on another machine).

gctransform/test/test_framework took ages because of the llinterpretation
of a raw_memclear() of the root stack, with 160'000 items!

Trying to do something cleaner about raw_memcopy() in llmemory.py.


Modified: pypy/dist/pypy/rlib/rctypes/rctypesobject.py
==============================================================================
--- pypy/dist/pypy/rlib/rctypes/rctypesobject.py	(original)
+++ pypy/dist/pypy/rlib/rctypes/rctypesobject.py	Wed Jan  3 16:26:37 2007
@@ -242,35 +242,29 @@
     try:
         return contentscls._ptrcls
     except AttributeError:
-        assert issubclass(contentscls, RCTypesObject)
-        if contentscls in _abstract_classes:
-            raise Exception("cannot call RPointer(%s) or "
-                            "pointer(x) if x degenerated to the base "
-                            "%s class" % (contentscls.__name__,
-                                          contentscls.__name__,))
 
         class RCTypesPtr(RCTypesObject):
-            CONTENTS  = contentscls.CDATATYPE
-            LLTYPE    = lltype.Ptr(CONTENTS)
+            LLTYPE = lltype.Ptr(lltype.ForwardReference())
             num_keepalives = 1
+            setpointertype = classmethod(_rpointer_set_pointer_type)
 
             def get_contents(self):
                 ptr = self.ll_ref(RCTypesPtr.CDATATYPE)
                 targetaddr = llmemory.cast_ptr_to_adr(ptr[0])
                 keepalive_until_here(self)
-                targetkeepalives = contentscls.num_keepalives
+                targetkeepalives = RCTypesPtr.CONTENTSCLS.num_keepalives
                 targetmemblock = self._getmemblock(0, targetkeepalives)
-                return contentscls(targetaddr, targetmemblock)
+                return RCTypesPtr.CONTENTSCLS(targetaddr, targetmemblock)
 
             def ref(self, index):
                 ptr = self.ll_ref(RCTypesPtr.CDATATYPE)
                 targetaddr = llmemory.cast_ptr_to_adr(ptr[0])
                 if index:
-                    targetaddr += ofs_item * index
+                    targetaddr += self._OFS_ITEM * index
                 keepalive_until_here(self)
-                targetkeepalives = contentscls.num_keepalives
+                targetkeepalives = RCTypesPtr.CONTENTSCLS.num_keepalives
                 targetmemblock = self._getmemblock(0, targetkeepalives)
-                return contentscls(targetaddr, targetmemblock)
+                return RCTypesPtr.CONTENTSCLS(targetaddr, targetmemblock)
 
             def set_contents(self, newcontentsbox):
                 targetaddr = newcontentsbox.addr
@@ -293,11 +287,30 @@
                 keepalive_until_here(self)
                 self._keepalivememblock(0, None)
 
-        ofs_item = llmemory.sizeof(contentscls.LLTYPE)
-        contentscls._ptrcls = RCTypesPtr
+        if contentscls is None:
+            pass   # forward pointer
+        else:
+            RCTypesPtr.setpointertype(contentscls)
         return RCTypesPtr
 RPointer._annspecialcase_ = 'specialize:memo'
 
+def _rpointer_set_pointer_type(RCTypesPtr, contentscls):
+    assert issubclass(contentscls, RCTypesObject)
+    if contentscls in _abstract_classes:
+        raise Exception("cannot call RPointer(%s) or "
+                        "pointer(x) if x degenerated to the base "
+                        "%s class" % (contentscls.__name__,
+                                      contentscls.__name__,))
+    RCTypesPtr.CONTENTSCLS = contentscls
+    RCTypesPtr.CONTENTS = contentscls.CDATATYPE
+    RCTypesPtr.LLTYPE.TO.become(RCTypesPtr.CONTENTS)
+    RCTypesPtr._OFS_ITEM = llmemory.sizeof(contentscls.LLTYPE)
+    RCTypesPtr.__name__ = 'RCTypes_%s' % (RCTypesPtr.LLTYPE,)
+    assert not hasattr(contentscls, '_ptrcls'), (
+        "the RPointer class corresponding to %r exists already" %
+        (contentscls,))
+    contentscls._ptrcls = RCTypesPtr
+
 def pointer(x):
     PTR = RPointer(x.__class__)
     p = PTR.allocate()

Modified: pypy/dist/pypy/rlib/rctypes/test/test_rctypesobject.py
==============================================================================
--- pypy/dist/pypy/rlib/rctypes/test/test_rctypesobject.py	(original)
+++ pypy/dist/pypy/rlib/rctypes/test/test_rctypesobject.py	Wed Jan  3 16:26:37 2007
@@ -266,6 +266,18 @@
         res = self.do(func)
         assert res == 101
 
+    def test_recursive_structure(self):
+        P1 = RPointer(None)
+        S1 = RStruct('S1', [('next', P1)])
+        P1.setpointertype(S1)
+        def func():
+            s1 = S1.allocate()
+            s2 = S1.allocate()
+            s2.ref_next().set_contents(s1)
+            return s2.ref_next().get_contents().sameaddr(s1)
+        res = self.do(func)
+        assert res == True
+
 POLICY = AnnotatorPolicy()
 POLICY.allow_someobjects = False
 

Modified: pypy/dist/pypy/rpython/llinterp.py
==============================================================================
--- pypy/dist/pypy/rpython/llinterp.py	(original)
+++ pypy/dist/pypy/rpython/llinterp.py	Wed Jan  3 16:26:37 2007
@@ -571,8 +571,7 @@
 
     def op_unsafe_call(self, TGT, f):
         checkadr(f)
-        assert f.offset is None
-        obj = self.llinterpreter.typer.type_system.deref(f.ob)
+        obj = self.llinterpreter.typer.type_system.deref(f.ref())
         assert hasattr(obj, 'graph') # don't want to think about that
         graph = obj.graph
         args = []
@@ -670,8 +669,8 @@
     def op_gc_call_rtti_destructor(self, rtti, addr):
         if hasattr(rtti._obj, 'destructor_funcptr'):
             d = rtti._obj.destructor_funcptr
-            ob = addr.get()
-            return self.op_direct_call(d, ob)
+            obptr = addr.ref()
+            return self.op_direct_call(d, obptr)
 
     def op_gc_deallocate(self, TYPE, addr):
         raise NotImplementedError("gc_deallocate")

Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/llmemory.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/llmemory.py	Wed Jan  3 16:26:37 2007
@@ -4,6 +4,7 @@
 
 # sizeof, offsetof
 
+import weakref
 from pypy.rlib.objectmodel import Symbolic
 from pypy.rpython.lltypesystem import lltype
 
@@ -21,11 +22,12 @@
             return NotImplemented
         return CompositeOffset(self, other)
 
-    def raw_malloc(self, rest):
+    def raw_malloc(self, rest, zero):
         raise NotImplementedError("raw_malloc(%r, %r)" % (self, rest))
 
-    def raw_memclear(self, adr):
-        raise NotImplementedError("raw_memclear(%r, %r)" % (self, adr))
+    def raw_memcopy(self, srcadr, dstsrc):
+        raise NotImplementedError("raw_memcopy(%r)" % (self,))
+
 
 class ItemOffset(AddressOffset):
 
@@ -46,56 +48,57 @@
     def __neg__(self):
         return ItemOffset(self.TYPE, -self.repeat)
 
-    def ref(self, firstitemref):
-        if isinstance(firstitemref, _obref):
-            parent, index = lltype.parentlink(firstitemref.ob._obj)
-            if parent is None:
-                raise TypeError("address + itemoffset: not the address"
-                                " of an array")
-            A = lltype.typeOf(parent)
-            assert isinstance(A, (lltype.Array, lltype.FixedSizeArray))
+    def ref(self, firstitemptr):
+        A = lltype.typeOf(firstitemptr).TO
+        if A == self.TYPE:
+            # for array of containers
+            parent, index = lltype.parentlink(firstitemptr._obj)
+            assert parent, "%r is not within a container" % (firstitemptr,)
+            assert isinstance(lltype.typeOf(parent),
+                              (lltype.Array, lltype.FixedSizeArray)), (
+                "%r is not within an array" % (firstitemptr,))
             if isinstance(index, str):
-                assert index.startswith("item")
-                index = int(index[4:])     # "itemN" => N
-            firstitemref = _arrayitemref(parent._as_ptr(), index)
-        assert isinstance(firstitemref, _arrayitemref)
-        array = firstitemref.array
-        assert lltype.typeOf(array).TO.OF == self.TYPE
-        index = firstitemref.index + self.repeat
-        return _arrayitemref(array, index)
+                assert index.startswith('item')    # itemN => N
+                index = int(index[4:])
+            return parent.getitem(index + self.repeat)._as_ptr()
+        elif isinstance(A, lltype.FixedSizeArray) and A.OF == self.TYPE:
+            # for array of primitives or pointers
+            return lltype.direct_ptradd(firstitemptr, self.repeat)
+        else:
+            raise TypeError('got %r, expected %r' % (A, self.TYPE))
 
-    def raw_malloc(self, rest):
+    def raw_malloc(self, rest, zero):
         assert not rest
         if (isinstance(self.TYPE, lltype.ContainerType)
             and self.TYPE._gckind == 'gc'):
             assert self.repeat == 1
-            p = lltype.malloc(self.TYPE, flavor='raw')
+            p = lltype.malloc(self.TYPE, flavor='raw', zero=zero)
             return cast_ptr_to_adr(p)
         else:
             T = lltype.FixedSizeArray(self.TYPE, self.repeat)
-            p = lltype.malloc(T, flavor='raw')
+            p = lltype.malloc(T, flavor='raw', zero=zero)
             array_adr = cast_ptr_to_adr(p)
             return array_adr + ArrayItemsOffset(T)
 
-    def raw_memclear(self, adr):
-        if (isinstance(self.TYPE, lltype.ContainerType) and self.repeat == 1):
-            from pypy.rpython.rctypes.rmodel import reccopy
-            fresh = lltype.malloc(self.TYPE, flavor='raw', zero=True)
-            reccopy(fresh, adr.get())
-        else:
-            assert adr.offset is not None
-            if isinstance(adr.offset, ArrayItemsOffset):
-                array = adr.ob
-            elif isinstance(adr.offset, CompositeOffset):
-                array = (adr + -adr.offset.offsets[-1]).get()
-            if isinstance(self.TYPE, lltype.ContainerType):
-                fresh = lltype.malloc(self.TYPE, flavor='raw', zero=True)
-                for i in range(self.repeat):
-                    reccopy(fresh, array[i])
-            else:
-                for i in range(self.repeat):
-                    array[i] = self.TYPE._defl()
-        
+    def raw_memcopy(self, srcadr, dstadr):
+        repeat = self.repeat
+        if repeat == 0:
+            return
+        from pypy.rpython.rctypes.rmodel import reccopy
+        if isinstance(self.TYPE, lltype.ContainerType):
+            PTR = lltype.Ptr(self.TYPE)
+        else:
+            PTR = lltype.Ptr(lltype.FixedSizeArray(self.TYPE, 1))
+        while True:
+            src = cast_adr_to_ptr(srcadr, PTR)
+            dst = cast_adr_to_ptr(dstadr, PTR)
+            reccopy(src, dst)
+            repeat -= 1
+            if repeat <= 0:
+                break
+            srcadr += ItemOffset(self.TYPE)
+            dstadr += ItemOffset(self.TYPE)
+
 
 class FieldOffset(AddressOffset):
 
@@ -106,33 +109,31 @@
     def __repr__(self):
         return "<FieldOffset %r %r>" % (self.TYPE, self.fldname)
 
-    def ref(self, containerref):
-        struct = containerref.get()
+    def ref(self, struct):
         if lltype.typeOf(struct).TO != self.TYPE:
             struct = lltype.cast_pointer(lltype.Ptr(self.TYPE), struct)
-        return _structfieldref(struct, self.fldname)
+        FIELD = getattr(self.TYPE, self.fldname)
+        if isinstance(FIELD, lltype.ContainerType):
+            return getattr(struct, self.fldname)
+        else:
+            return lltype.direct_fieldptr(struct, self.fldname)
 
-    def raw_malloc(self, rest, parenttype=None):
+    def raw_malloc(self, rest, parenttype=None, zero=False):
         if self.fldname != self.TYPE._arrayfld:
-            return AddressOffset.raw_malloc(self, rest)   # for the error msg
+            # for the error msg
+            return AddressOffset.raw_malloc(self, rest, zero=zero)
         assert rest
-        return rest[0].raw_malloc(rest[1:], parenttype=parenttype or self.TYPE)
+        return rest[0].raw_malloc(rest[1:], parenttype=parenttype or self.TYPE,
+                                            zero=zero)
 
-    def raw_memclear(self, adr):
+    def raw_memcopy(self, srcadr, dstadr):
         if self.fldname != self.TYPE._arrayfld:
-            return AddressOffset.raw_memclear(adr)   # for the error msg
-        structptr = adr.get()
-        for name in self.TYPE._names[:-1]:
-            FIELDTYPE = getattr(self.TYPE, name) 
-            if isinstance(FIELDTYPE, lltype.ContainerType):
-                fresh = lltype.malloc(FIELDTYPE, raw=True, zero=True)
-                from pypy.rpython.rctypes.rmodel import reccopy
-                fresh = lltype.malloc(self.TYPE, flavor='raw', zero=True)
-                reccopy(fresh, getattr(structptr, name)._obj)
-            else:
-                setattr(structptr, name, FIELDTYPE._defl())
-
-    
+            return AddressOffset.raw_memcopy(srcadr, dstadr) #for the error msg
+        PTR = lltype.Ptr(self.TYPE)
+        src = cast_adr_to_ptr(srcadr, PTR)
+        dst = cast_adr_to_ptr(dstadr, PTR)
+        from pypy.rpython.rctypes.rmodel import reccopy
+        reccopy(src, dst)
 
 
 class CompositeOffset(AddressOffset):
@@ -165,19 +166,21 @@
         ofs.reverse()
         return CompositeOffset(*ofs)
 
-    def ref(self, ref):
+    def ref(self, ptr):
         for item in self.offsets:
-            ref = item.ref(ref)
-        return ref
+            ptr = item.ref(ptr)
+        return ptr
 
-    def raw_malloc(self, rest):
-        return self.offsets[0].raw_malloc(self.offsets[1:] + rest)
+    def raw_malloc(self, rest, zero):
+        return self.offsets[0].raw_malloc(self.offsets[1:] + rest, zero=zero)
 
-    def raw_memclear(self, adr):
+    def raw_memcopy(self, srcadr, dstadr):
         for o in self.offsets[:-1]:
-            o.raw_memclear(adr)
-            adr += o
-        o.raw_memclear(adr)
+            o.raw_memcopy(srcadr, dstadr)
+            srcadr += o
+            dstadr += o
+        o = self.offsets[-1]
+        o.raw_memcopy(srcadr, dstadr)
 
 
 class ArrayItemsOffset(AddressOffset):
@@ -188,12 +191,14 @@
     def __repr__(self):
         return '< ArrayItemsOffset %r >' % (self.TYPE,)
 
-    def ref(self, arrayref):
-        array = arrayref.get()
-        assert lltype.typeOf(array).TO == self.TYPE
-        return _arrayitemref(array, index=0)
+    def ref(self, arrayptr):
+        assert lltype.typeOf(arrayptr).TO == self.TYPE
+        if isinstance(self.TYPE.OF, lltype.ContainerType):
+            return arrayptr[0]
+        else:
+            return lltype.direct_arrayitems(arrayptr)
 
-    def raw_malloc(self, rest, parenttype=None):
+    def raw_malloc(self, rest, parenttype=None, zero=False):
         if rest:
             assert len(rest) == 1
             assert isinstance(rest[0], ItemOffset)
@@ -204,11 +209,12 @@
         if self.TYPE._hints.get('isrpystring'):
             count -= 1  # because malloc() will give us the extra char for free
         p = lltype.malloc(parenttype or self.TYPE, count,
-                          immortal = self.TYPE._gckind == 'raw')
+                          immortal = self.TYPE._gckind == 'raw',
+                          zero = zero)
         return cast_ptr_to_adr(p)
 
-    def raw_memclear(self, adr):
-        # should really zero out the length field, but we can't
+    def raw_memcopy(self, srcadr, dstadr):
+        # should really copy the length field, but we can't
         pass
 
 
@@ -220,10 +226,9 @@
     def __repr__(self):
         return '< ArrayLengthOffset %r >' % (self.TYPE,)
 
-    def ref(self, arrayref):
-        array = arrayref.get()
-        assert lltype.typeOf(array).TO == self.TYPE
-        return _arraylenref(array)
+    def ref(self, arrayptr):
+        assert lltype.typeOf(arrayptr).TO == self.TYPE
+        return lltype._arraylenref._makeptr(arrayptr._obj, arrayptr._solid)
 
 
 class GCHeaderOffset(AddressOffset):
@@ -236,22 +241,21 @@
     def __neg__(self):
         return GCHeaderAntiOffset(self.gcheaderbuilder)
 
-    def ref(self, headerref):
-        header = headerref.get()
-        gcptr = self.gcheaderbuilder.object_from_header(header)
-        return _obref(gcptr)
+    def ref(self, headerptr):
+        gcptr = self.gcheaderbuilder.object_from_header(headerptr)
+        return gcptr
 
-    def raw_malloc(self, rest):
+    def raw_malloc(self, rest, zero):
         assert rest
         if isinstance(rest[0], GCHeaderAntiOffset):
-            return rest[1].raw_malloc(rest[2:])    # just for fun
-        gcobjadr = rest[0].raw_malloc(rest[1:])
-        headerptr = self.gcheaderbuilder.new_header(gcobjadr.get())
+            return rest[1].raw_malloc(rest[2:], zero=zero)    # just for fun
+        gcobjadr = rest[0].raw_malloc(rest[1:], zero=zero)
+        headerptr = self.gcheaderbuilder.new_header(gcobjadr.ptr)
         return cast_ptr_to_adr(headerptr)
 
-    def raw_memclear(self, adr):
-        headerptr = adr.get()
-        sizeof(lltype.typeOf(headerptr).TO).raw_memclear(cast_ptr_to_adr(headerptr))
+    def raw_memcopy(self, srcadr, dstadr):
+        from pypy.rpython.rctypes.rmodel import reccopy
+        reccopy(srcadr.ptr, dstadr.ptr)
 
 class GCHeaderAntiOffset(AddressOffset):
     def __init__(self, gcheaderbuilder):
@@ -263,85 +267,14 @@
     def __neg__(self):
         return GCHeaderOffset(self.gcheaderbuilder)
 
-    def ref(self, gcptrref):
-        gcptr = gcptrref.get()
+    def ref(self, gcptr):
         headerptr = self.gcheaderbuilder.header_of_object(gcptr)
-        return _obref(headerptr)
+        return headerptr
 
-    def raw_malloc(self, rest):
+    def raw_malloc(self, rest, zero):
         assert len(rest) >= 2
         assert isinstance(rest[0], GCHeaderOffset)
-        return rest[1].raw_malloc(rest[2:])
-
-
-class _arrayitemref(object):
-    def __init__(self, array, index):
-        self.array = array
-        self.index = index
-    def get(self):
-        return self.array[self.index]
-    def set(self, value):
-        self.array[self.index] = value
-    def __eq__(self, other):
-        if self.__class__ is not other.__class__:
-            return False
-        return self.array._same_obj(other.array) and \
-               self.index == other.index
-    def __ne__(self, other):
-        return not (self == other)
-    def type(self):
-        return lltype.typeOf(self.array).TO.OF
-
-class _arraylenref(object):
-    def __init__(self, array):
-        self.array = array
-    def get(self):
-        return len(self.array)
-    def set(self, value):
-        if value != len(self.array):
-            raise Exception("can't change the length of an array")
-    def __eq__(self, other):
-        if self.__class__ is not other.__class__:
-            return False
-        return self.array._same_obj(other.array)
-    def __ne__(self, other):
-        return not (self == other)
-    def type(self):
-        return lltype.Signed
-
-class _structfieldref(object):
-    def __init__(self, struct, fieldname):
-        self.struct = struct
-        self.fieldname = fieldname
-    def get(self):
-        return getattr(self.struct, self.fieldname)
-    def set(self, value):
-        setattr(self.struct, self.fieldname, value)
-    def __eq__(self, other):
-        if self.__class__ is not other.__class__:
-            return False
-        return self.struct._same_obj(other.struct) and \
-               self.fieldname == other.fieldname
-    def __ne__(self, other):
-        return not (self == other)
-    def type(self):
-        return getattr(lltype.typeOf(self.struct).TO, self.fieldname)
-
-class _obref(object):
-    def __init__(self, ob):
-        self.ob = ob
-    def get(self):
-        return self.ob
-    def set(self, value):
-        raise Exception("can't assign to whole object")
-    def __eq__(self, other):
-        if self.__class__ is not other.__class__:
-            return False
-        return self.ob._same_obj(other.ob)
-    def __ne__(self, other):
-        return not (self == other)
-    def type(self):
-        return lltype.typeOf(self.ob)
+        return rest[1].raw_malloc(rest[2:], zero=zero)
 
 # ____________________________________________________________
 
@@ -367,30 +300,23 @@
 # -------------------------------------------------------------
 
 class fakeaddress(object):
-    # NOTE: the 'ob' in the addresses must be normalized.
+    # NOTE: the 'ptr' in the addresses must be normalized.
     # Use cast_ptr_to_adr() instead of directly fakeaddress() if unsure.
-    def __init__(self, ob, offset=None):
-        self.ob = ob
-        self.offset = offset
+    def __init__(self, ptr):
+        self.ptr = ptr or None   # null ptr => None
 
     def __repr__(self):
-        if self.ob is None:
+        if self.ptr is None:
             s = 'NULL'
         else:
-            s = str(self.ob)
-        if self.offset is not None:
-            s = '%s + %r' % (s, self.offset)
+            s = str(self.ptr)
         return '<fakeaddr %s>' % (s,)
 
     def __add__(self, other):
         if isinstance(other, AddressOffset):
-            if self.offset is None:
-                offset = other
-            else:
-                offset = self.offset + other
-            res = fakeaddress(self.ob, offset)
-            res.ref() # sanity check
-            return res
+            if self.ptr is None:
+                raise NullAddressError("offset from NULL address")
+            return fakeaddress(other.ref(self.ptr))
         if other == 0:
             return self
         return NotImplemented
@@ -403,62 +329,71 @@
         return NotImplemented
 
     def __nonzero__(self):
-        return self.ob is not None
+        return self.ptr is not None
 
     def __eq__(self, other):
-        if not isinstance(other, fakeaddress):
-            return False
-        if self.ob is None:
-            return other.ob is None
-        if other.ob is None:
-            return False
-        return self.ref() == other.ref()
+        if isinstance(other, fakeaddress):
+            obj1 = self.ptr
+            obj2 = other.ptr
+            if obj1 is not None: obj1 = obj1._obj
+            if obj2 is not None: obj2 = obj2._obj
+            return obj1 == obj2
+        else:
+            return NotImplemented
 
     def __ne__(self, other):
-        return not (self == other)
+        if isinstance(other, fakeaddress):
+            return not (self == other)
+        else:
+            return NotImplemented
 
     def ref(self):
         if not self:
             raise NullAddressError
-        ref = _obref(self.ob)
-        if self.offset is not None:
-            ref = self.offset.ref(ref)
-        return ref
+        return self.ptr
 
-    def get(self):
-        return self.ref().get()
+##    def get(self):
+##        return self.ref().get()
 
-    def set(self, value):
-        self.ref().set(value)
+##    def set(self, value):
+##        self.ref().set(value)
 
     def _cast_to_ptr(self, EXPECTED_TYPE):
-        if not self:
-            return lltype.nullptr(EXPECTED_TYPE.TO)
-        ref = self.ref()
-        if (isinstance(ref, _arrayitemref) and
-            isinstance(EXPECTED_TYPE.TO, lltype.FixedSizeArray) and
-            ref.type() == EXPECTED_TYPE.TO.OF):
-            # special case that requires direct_arrayitems
-            p_items = lltype.direct_arrayitems(ref.array)
-            return lltype.direct_ptradd(p_items, ref.index)
-        elif (isinstance(ref, _structfieldref) and
-              isinstance(EXPECTED_TYPE.TO, lltype.FixedSizeArray) and
-              ref.type() == EXPECTED_TYPE.TO.OF):
-            # special case that requires direct_fieldptr
-            return lltype.direct_fieldptr(ref.struct,
-                                          ref.fieldname)
-        else:
-            result = ref.get()
+        if self:
+            PTRTYPE = lltype.typeOf(self.ptr)
             if (isinstance(EXPECTED_TYPE.TO, lltype.OpaqueType) or
-                isinstance(lltype.typeOf(result).TO, lltype.OpaqueType)):
-                return lltype.cast_opaque_ptr(EXPECTED_TYPE, result)
+                isinstance(PTRTYPE.TO, lltype.OpaqueType)):
+                return lltype.cast_opaque_ptr(EXPECTED_TYPE, self.ptr)
             else:
                 # regular case
-                return lltype.cast_pointer(EXPECTED_TYPE, result)
+                return lltype.cast_pointer(EXPECTED_TYPE, self.ptr)
+        else:
+            return lltype.nullptr(EXPECTED_TYPE.TO)
+
+##        if (isinstance(ref, _arrayitemref) and
+##            isinstance(EXPECTED_TYPE.TO, lltype.FixedSizeArray) and
+##            ref.type() == EXPECTED_TYPE.TO.OF):
+##            # special case that requires direct_arrayitems
+##            p_items = lltype.direct_arrayitems(ref.array)
+##            return lltype.direct_ptradd(p_items, ref.index)
+##        elif (isinstance(ref, _structfieldref) and
+##              isinstance(EXPECTED_TYPE.TO, lltype.FixedSizeArray) and
+##              ref.type() == EXPECTED_TYPE.TO.OF):
+##            # special case that requires direct_fieldptr
+##            return lltype.direct_fieldptr(ref.struct,
+##                                          ref.fieldname)
+##        else:
+##            result = ref.get()
+##            if (isinstance(EXPECTED_TYPE.TO, lltype.OpaqueType) or
+##                isinstance(lltype.typeOf(result).TO, lltype.OpaqueType)):
+##                return lltype.cast_opaque_ptr(EXPECTED_TYPE, result)
+##            else:
+##                # regular case
+##                return lltype.cast_pointer(EXPECTED_TYPE, result)
 
     def _cast_to_int(self):
         if self:
-            return self.get()._cast_to_int()
+            return self.ptr._cast_to_int()
         else:
             return 0
 
@@ -482,25 +417,25 @@
     def __init__(self, addr):
         self.addr = addr
     def __getitem__(self, index):
-        addr = self.addr
+        ptr = self.addr.ref()
         if index != 0:
-            addr += ItemOffset(addr.ref().type(), index)
-        return self.erase_type(addr.get())
+            ptr = lltype.direct_ptradd(ptr, index)
+        return self.read_from_ptr(ptr)
 
     def __setitem__(self, index, value):
         assert lltype.typeOf(value) == self.TYPE
-        addr = self.addr
+        ptr = self.addr.ref()
         if index != 0:
-            addr += ItemOffset(addr.ref().type(), index)
-        addr.set(self.unerase_type(addr.ref().type(), value))
+            ptr = lltype.direct_ptradd(ptr, index)
+        self.write_into_ptr(ptr, value)
 
-    def erase_type(self, value):
+    def read_from_ptr(self, ptr):
+        value = ptr[0]
         assert lltype.typeOf(value) == self.TYPE
         return value
 
-    def unerase_type(self, TARGETTYPE, value):
-        assert lltype.typeOf(value) == TARGETTYPE
-        return value
+    def write_into_ptr(self, ptr, value):
+        ptr[0] = value
 
 
 class _signed_fakeaccessor(_fakeaccessor):
@@ -512,7 +447,8 @@
 class _address_fakeaccessor(_fakeaccessor):
     TYPE = Address
 
-    def erase_type(self, value):
+    def read_from_ptr(self, ptr):
+        value = ptr[0]
         if isinstance(value, lltype._ptr):
             return value._cast_to_adr()
         elif lltype.typeOf(value) == Address:
@@ -520,13 +456,15 @@
         else:
             raise TypeError(value)
 
-    def unerase_type(self, TARGETTYPE, value):
+    def write_into_ptr(self, ptr, value):
+        TARGETTYPE = lltype.typeOf(ptr).TO.OF
         if TARGETTYPE == Address:
-            return value
+            pass
         elif isinstance(TARGETTYPE, lltype.Ptr):
-            return cast_adr_to_ptr(value, TARGETTYPE)
+            value = cast_adr_to_ptr(value, TARGETTYPE)
         else:
-            raise TypeError(TARGETTYPE, value)
+            raise TypeError(TARGETTYPE)
+        ptr[0] = value
 
 
 fakeaddress.signed = property(_signed_fakeaccessor)
@@ -552,8 +490,6 @@
 
 # ____________________________________________________________
 
-import weakref
-
 class fakeweakaddress(object):
     def __init__(self, ob):
         if ob is not None:
@@ -607,12 +543,19 @@
 def raw_malloc(size):
     if not isinstance(size, AddressOffset):
         raise NotImplementedError(size)
-    return size.raw_malloc([])
+    return size.raw_malloc([], zero=False)
 
 def raw_free(adr):
-    # xxx crash if you get only the header of a gc object
-    assert isinstance(adr.ob._obj, lltype._parentable)
-    adr.ob._as_obj()._free()
+    # try to free the whole object if 'adr' is the address of the header
+    from pypy.rpython.memory.gcheader import GCHeaderBuilder
+    try:
+        objectptr = GCHeaderBuilder.object_from_header(adr.ptr)
+    except KeyError:
+        pass
+    else:
+        raw_free(cast_ptr_to_adr(objectptr))
+    assert isinstance(adr.ref()._obj, lltype._parentable)
+    adr.ptr._as_obj()._free()
 
 def raw_malloc_usage(size):
     if isinstance(size, AddressOffset):
@@ -625,58 +568,64 @@
     if not isinstance(size, AddressOffset):
         raise NotImplementedError(size)
     assert lltype.typeOf(adr) == Address
-    size.raw_memclear(adr)
+    zeroadr = size.raw_malloc([], zero=True)
+    size.raw_memcopy(zeroadr, adr)
 
 def raw_memcopy(source, dest, size):
-    source = source.get()
-    dest = dest.get()
-    # this check would be nice...
-    #assert sizeof(lltype.typeOf(source)) == sizeof(lltype.typeOf(dest)) == size
-    from pypy.rpython.rctypes.rmodel import reccopy
-    reccopy(source, dest)
+    assert lltype.typeOf(source) == Address
+    assert lltype.typeOf(dest)   == Address
+    size.raw_memcopy(source, dest)
 
 # ____________________________________________________________
 
+ARENA_ITEM = lltype.OpaqueType('ArenaItem')
+
 class _arena(object):
+    #_cache = weakref.WeakKeyDictionary()    # {obj: _arenaitem}
 
-    def __init__(self, rng):
+    def __init__(self, rng, zero):
         self.rng = rng
+        self.zero = zero
         self.items = []
 
-class ArenaItem(AddressOffset):
-    
-    def __init__(self, nr):
+    def getitemaddr(self, n):
+        while len(self.items) <= n:
+            self.items.append(_arenaitem(self, len(self.items)))
+        return fakeaddress(self.items[n]._as_ptr())
+
+class _arenaitem(lltype._container):
+    _TYPE = ARENA_ITEM
+
+    def __init__(self, arena, nr):
+        self.arena = arena
         self.nr = nr
+        self.reserved_size = None
+
+    def reserve(self, size):
+        if self.reserved_size is None:
+            # xxx check that we are not larger than unitsize*n
+            itemadr = raw_malloc(size)
+            self.container = itemadr.ptr._obj
+            #_arena._cache[itemadr.ptr._obj] = self
+        else:
+            assert size == self.reserved_size
 
-    def ref(self, ref):
-        assert isinstance(ref, _obref)
-        assert isinstance(ref.ob, _arena)
-        arena = ref.ob
-        itemadr = arena.items[self.nr]
-        return itemadr.ref()
-        
 class ArenaRange(AddressOffset):
     def __init__(self, unitsize, n):
         self.unitsize = unitsize
         self.n = n
 
-    def raw_malloc(self, rest):
+    def raw_malloc(self, rest, zero=False):
         assert not rest
-        return fakeaddress(_arena(self), ArenaItem(0))
+        arena = _arena(self, zero=zero)
+        return arena.getitemaddr(0)
         
 def arena(TYPE, n):
     return ArenaRange(sizeof(TYPE), n)
 
 def bump(adr, size):
-    assert isinstance(adr.ob, _arena)
-    assert isinstance(adr.offset, ArenaItem)
-    arena = adr.ob
-    nr = adr.offset.nr
-    if len(arena.items) == nr: # reserve
-        # xxx check that we are not larger than unitsize*n
-        itemadr = raw_malloc(size)
-        arena.items.append(itemadr)
-    else:
-        assert nr < len(arena.items)
-        # xxx check that size matches
-    return fakeaddress(arena, ArenaItem(nr+1))
+    baseptr = cast_adr_to_ptr(adr, lltype.Ptr(ARENA_ITEM))
+    baseptr._obj.reserve(size)
+    arena = baseptr._obj.arena
+    nr = baseptr._obj.nr
+    return arena.getitemaddr(nr + 1)

Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lltype.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/lltype.py	Wed Jan  3 16:26:37 2007
@@ -759,6 +759,8 @@
     CURTYPE = typeOf(ptr)
     if not isinstance(CURTYPE, Ptr) or not isinstance(PTRTYPE, Ptr):
         raise TypeError, "can only cast pointers to other pointers"
+    if CURTYPE == PTRTYPE:
+        return ptr
     if CURTYPE.TO._gckind != PTRTYPE.TO._gckind:
         raise TypeError("cast_opaque_ptr() cannot change the gc status: "
                         "%s to %s" % (CURTYPE, PTRTYPE))
@@ -1151,12 +1153,13 @@
         if isinstance(self._T, FuncType):
             return llmemory.fakeaddress(self)
         elif isinstance(self._obj, _subarray):
-            # return an address built as an offset in the whole array
-            parent, parentindex = parentlink(self._obj)
-            T = typeOf(parent)
-            addr = llmemory.fakeaddress(normalizeptr(_ptr(Ptr(T), parent)))
-            addr += llmemory.itemoffsetof(T, parentindex)
-            return addr
+            return llmemory.fakeaddress(self)
+##            # return an address built as an offset in the whole array
+##            parent, parentindex = parentlink(self._obj)
+##            T = typeOf(parent)
+##            addr = llmemory.fakeaddress(normalizeptr(_ptr(Ptr(T), parent)))
+##            addr += llmemory.itemoffsetof(T, parentindex)
+##            return addr
         else:
             # normal case
             return llmemory.fakeaddress(normalizeptr(self))
@@ -1417,7 +1420,16 @@
             raise
 
     def setitem(self, index, value):
-        self.items[index] = value
+        try:
+            self.items[index] = value
+        except IndexError:
+            if (self._TYPE._hints.get('isrpystring', False) and
+                index == len(self.items)):
+                # special hack for the null terminator: can overwrite it
+                # with another null
+                assert value == '\x00'
+                return
+            raise
 
 assert not '__dict__' in dir(_array)
 assert not '__dict__' in dir(_struct)
@@ -1432,6 +1444,11 @@
         _parentable.__init__(self, TYPE)
         self._setparentstructure(parent, baseoffset_or_fieldname)
 
+    def __repr__(self):
+        
+        return '<_subarray at %r in %r>' % (self._parent_index,
+                                            self._parentstructure())
+
     def getlength(self):
         assert isinstance(self._TYPE, FixedSizeArray)
         return self._TYPE.length
@@ -1484,6 +1501,46 @@
         raise NotImplementedError('_subarray._getid()')
 
 
+class _arraylenref(_parentable):
+    """Pseudo-reference to the length field of an array.
+    Only used internally by llmemory to implement ArrayLengthOffset.
+    """
+    _kind = "arraylenptr"
+    _cache = weakref.WeakKeyDictionary()  # array -> _arraylenref
+
+    def __init__(self, array):
+        TYPE = FixedSizeArray(Signed, 1)
+        _parentable.__init__(self, TYPE)
+        self.array = array
+
+    def getlength(self):
+        return 1
+
+    def getbounds(self):
+        return 0, 1
+
+    def getitem(self, index, uninitialized_ok=False):
+        assert index == 0
+        return self.array.getlength()
+
+    def setitem(self, index, value):
+        assert index == 0
+        if value != self.array.getlength():
+            raise Exception("can't change the length of an array")
+
+    def _makeptr(array, solid=False):
+        try:
+            lenref = _arraylenref._cache[array]
+        except KeyError:
+            lenref = _arraylenref(array)
+            _arraylenref._cache[array] = lenref
+        return _ptr(Ptr(lenref._TYPE), lenref, solid)
+    _makeptr = staticmethod(_makeptr)
+
+    def _getid(self):
+        raise NotImplementedError('_arraylenref._getid()')
+
+
 class _func(_container):
     def __init__(self, TYPE, **attrs):
         self._TYPE = TYPE

Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py	Wed Jan  3 16:26:37 2007
@@ -9,10 +9,10 @@
     s.x = 123
     s.y = 456
     a = fakeaddress(s)
-    assert a.get() == s
+    assert a.ref() == s
     b = a + FieldOffset(S, 'x')
-    assert b.get() == 123
-    b.set(234)
+    assert b.signed[0] == 123
+    b.signed[0] = 234
     assert s.x == 234
 
 def test_composite():
@@ -22,10 +22,10 @@
     s2.s.x = 123
     s2.s.y = 456
     a = fakeaddress(s2)
-    assert a.get() == s2
+    assert a.ref() == s2
     b = a + FieldOffset(S2, 's') + FieldOffset(S1, 'x')
-    assert b.get() == 123
-    b.set(234)
+    assert b.signed[0] == 123
+    b.signed[0] = 234
     assert s2.s.x == 234
     
 def test_array():
@@ -36,8 +36,8 @@
     b = a + ArrayItemsOffset(A)
     b += ItemOffset(lltype.Signed)*2
     b += ItemOffset(lltype.Signed)
-    assert b.get() == 123
-    b.set(14)
+    assert b.signed[0] == 123
+    b.signed[0] = 14
     assert x[3] == 14
     
 def test_dont_mix_offsets_and_ints():

Modified: pypy/dist/pypy/rpython/memory/gcheader.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gcheader.py	(original)
+++ pypy/dist/pypy/rpython/memory/gcheader.py	Wed Jan  3 16:26:37 2007
@@ -17,8 +17,9 @@
     def header_of_object(self, gcptr):
         return self.obj2header[gcptr._as_obj()]
 
-    def object_from_header(self, headerptr):
+    def object_from_header(headerptr):
         return header2obj[headerptr._as_obj()]
+    object_from_header = staticmethod(object_from_header)
 
     def get_header(self, gcptr):
         return self.obj2header.get(gcptr._as_obj(), None)

Modified: pypy/dist/pypy/rpython/memory/gctransform/framework.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform/framework.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform/framework.py	Wed Jan  3 16:26:37 2007
@@ -24,10 +24,10 @@
     use_stackless = False
     extra_static_slots = 0
     finished_tables = False
+    root_stack_depth = 163840
 
     from pypy.rpython.memory.gc import MarkSweepGC as GCClass
-    GC_PARAMS = {'start_heap_size': 8*1024*1024 # XXX adjust
-                 }
+    GC_PARAMS = {'start_heap_size': 8*1024*1024} # XXX adjust
 
     def __init__(self, translator):
         from pypy.rpython.memory.support import get_address_linked_list
@@ -228,7 +228,7 @@
     def build_stack_root_iterator(self):
         gcdata = self.gcdata
         sizeofaddr = llmemory.sizeof(llmemory.Address)
-        rootstacksize = sizeofaddr * 163840    # XXX adjust
+        rootstacksize = sizeofaddr * self.root_stack_depth
 
         class StackRootIterator:
             _alloc_flavor_ = 'raw'

Modified: pypy/dist/pypy/rpython/memory/gctransform/test/test_framework.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform/test/test_framework.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform/test/test_framework.py	Wed Jan  3 16:26:37 2007
@@ -8,7 +8,8 @@
 import py
 
 class FrameworkGcPolicy2(FrameworkGcPolicy):
-    transformerclass = FrameworkGCTransformer
+    class transformerclass(FrameworkGCTransformer):
+        root_stack_depth = 100
 
 def test_framework_simple():
     def g(x):

Modified: pypy/dist/pypy/translator/c/database.py
==============================================================================
--- pypy/dist/pypy/translator/c/database.py	(original)
+++ pypy/dist/pypy/translator/c/database.py	Wed Jan  3 16:26:37 2007
@@ -4,7 +4,6 @@
      ContainerType, OpaqueType, FixedSizeArray, _uninitialized
 from pypy.rpython.lltypesystem import lltype
 from pypy.rpython.lltypesystem.llmemory import Address
-from pypy.rpython.memory.lladdress import NULL
 from pypy.tool.sourcetools import valid_identifier
 from pypy.translator.c.primitive import PrimitiveName, PrimitiveType
 from pypy.translator.c.primitive import PrimitiveErrorValue
@@ -139,7 +138,6 @@
         try:
             node = self.containernodes[container]
         except KeyError:
-            assert not self.completed
             T = typeOf(container)
             if isinstance(T, (lltype.Array, lltype.Struct)):
                 if hasattr(self.gctransformer, 'consider_constant'):
@@ -150,6 +148,10 @@
             self.containerlist.append(node)
             kind = getattr(node, 'nodekind', '?')
             self.containerstats[kind] = self.containerstats.get(kind, 0) + 1
+            if self.completed:
+                assert not node.globalcontainer
+                # non-global containers are found very late, e.g. _subarrays
+                # via addresses introduced by the GC transformer
         return node
 
     def get(self, obj):

Modified: pypy/dist/pypy/translator/c/primitive.py
==============================================================================
--- pypy/dist/pypy/translator/c/primitive.py	(original)
+++ pypy/dist/pypy/translator/c/primitive.py	Wed Jan  3 16:26:37 2007
@@ -2,11 +2,10 @@
 from pypy.rlib.objectmodel import Symbolic, ComputedIntSymbolic
 from pypy.rlib.objectmodel import CDefinedIntSymbolic
 from pypy.rpython.lltypesystem.lltype import *
-from pypy.rpython.lltypesystem.llmemory import Address, fakeaddress, \
+from pypy.rpython.lltypesystem.llmemory import Address, \
      AddressOffset, ItemOffset, ArrayItemsOffset, FieldOffset, \
      CompositeOffset, ArrayLengthOffset, WeakGcAddress, fakeweakaddress, \
      GCHeaderOffset
-from pypy.rpython.memory.lladdress import NULL
 from pypy.translator.c.support import cdecl
 
 # ____________________________________________________________
@@ -99,24 +98,10 @@
     return '%d' % ord(value)
 
 def name_address(value, db):
-    if value is NULL:
-        return 'NULL'
-    assert isinstance(value, fakeaddress)
-    if value.offset is None:
-        if value.ob is None:
-            return 'NULL'
-        else:
-            if isinstance(typeOf(value.ob), ContainerType):
-                return db.getcontainernode(value.ob).ptrname
-            else:
-                return db.get(value.ob)
+    if value:
+        return db.get(value.ref())
     else:
-        if isinstance(typeOf(value.ob), ContainerType):
-            base = db.getcontainernode(value.ob).ptrname
-        else:
-            base = db.get(value.ob)
-        
-        return '(void*)(((char*)(%s)) + (%s))'%(base, db.get(value.offset))
+        return 'NULL'
 
 def name_weakgcaddress(value, db):
     assert isinstance(value, fakeweakaddress)

Modified: pypy/dist/pypy/translator/llvm/database.py
==============================================================================
--- pypy/dist/pypy/translator/llvm/database.py	(original)
+++ pypy/dist/pypy/translator/llvm/database.py	Wed Jan  3 16:26:37 2007
@@ -147,8 +147,8 @@
             if type_ is llmemory.Address:
                 # prepare the constant data which this address references
                 assert isinstance(value, llmemory.fakeaddress)
-                if value.ob is not None:
-                    self.prepare_constant(lltype.typeOf(value.ob), value.ob)
+                if value:
+                    self.prepare_constant(lltype.typeOf(value.ptr), value.ptr)
             return
 
         if isinstance(type_, lltype.Ptr) and isinstance(value._obj, int):
@@ -181,8 +181,8 @@
                 # special cases for address
                 if ct is llmemory.Address:
                     fakedaddress = const_or_var.value
-                    if fakedaddress is not None and fakedaddress.ob is not None:
-                        ptrvalue = fakedaddress.ob
+                    if fakedaddress:
+                        ptrvalue = fakedaddress.ptr
                         ct = lltype.typeOf(ptrvalue)
                     else:
                         return                        
@@ -465,41 +465,14 @@
         return repr
 
     def repr_address(self, type_, value):
-        if value is NULL:
+        if not value:
             return 'null'
-
-        assert isinstance(value, llmemory.fakeaddress)
-
-        if value.offset is None:
-            if value.ob is None:
-                return 'null'
-            else:
-                obj = value.ob._obj
-                typename = self.database.repr_type(lltype.typeOf(obj))
-                ref = self.database.repr_name(obj)
-        else:
-            from_, indices, to = self.get_offset(value.offset)
-            indices_as_str = ", ".join("%s %s" % (w, i) for w, i in indices)
-
-            #original_typename = self.database.repr_type(from_)
-            #orignal_ref = self.database.repr_name(value.ob._obj)
-            #
-            #typename = self.database.repr_type(to)
-            #ref = "getelementptr(%s* %s, %s)" % (original_typename,
-            #                                     orignal_ref,
-            #                                     indices_as_str)
-
-            ptrtype = self.database.repr_type(lltype.Ptr(from_))
-            node = self.database.obj2node[value.ob._obj]
-            parentref = node.get_pbcref(ptrtype)
-
-            typename = self.database.repr_type(to)
-            ref = "getelementptr(%s %s, %s)" % (ptrtype, parentref,
-                                                indices_as_str)
-
+        obj = value.ptr._obj
+        typename = self.database.repr_type(lltype.typeOf(obj))
+        ref = self.database.repr_name(obj)
         res = "cast(%s* %s to sbyte*)" % (typename, ref)
-        return res    
-    
+        return res
+
     def repr_weakgcaddress(self, type_, value):
         assert isinstance(value, llmemory.fakeweakaddress)
         log.WARNING("XXX weakgcaddress completely ignored...")



More information about the Pypy-commit mailing list