Author: Armin Rigo <[email protected]>
Branch: array-overallocation-in-nursery
Changeset: r67511:9c69606d0734
Date: 2013-10-22 14:46 +0200
http://bitbucket.org/pypy/pypy/changeset/9c69606d0734/

Log:    (fijal, arigo) in-progress

diff --git a/rpython/memory/gc/base.py b/rpython/memory/gc/base.py
--- a/rpython/memory/gc/base.py
+++ b/rpython/memory/gc/base.py
@@ -131,6 +131,28 @@
     def get_size_incl_hash(self, obj):
         return self.get_size(obj)
 
+    def _shrink_and_get_size_for_typeid(self, obj, typeid):
+        # Get the size of the object; but for overallocated arrays, we
+        # first fix the allocated length in-place to reduce it to the
+        # used length.
+        size = self.fixed_size(typeid)
+        if self.is_varsize(typeid):
+            ofslen = self.varsize_offset_to_length(typeid)
+            ofsusedlen = self.varsize_offset_to_used_length(typeid)
+            lenaddr = obj + ofsusedlen
+            length = lenaddr.signed[0]
+            if not (ofsusedlen == ofslen):
+                (obj + ofslen).signed[0] = length
+            size += length * self.varsize_item_sizes(typeid)
+            size = llarena.round_up_for_allocation(size)
+            # XXX maybe we should parametrize round_up_for_allocation()
+            # per GC; if we do, we also need to fix the call in
+            # gctypelayout.encode_type_shape()
+        return size
+
+    def shrink_and_get_size(self, obj):
+        return self._shrink_and_get_size_for_typeid(obj, self.get_type_id(obj))
+
     def malloc(self, typeid, length=0, zero=False):
         """For testing.  The interface used by the gctransformer is
         the four malloc_[fixed,var]size[_clear]() functions.
diff --git a/rpython/memory/gc/incminimark.py b/rpython/memory/gc/incminimark.py
--- a/rpython/memory/gc/incminimark.py
+++ b/rpython/memory/gc/incminimark.py
@@ -1618,7 +1618,7 @@
             # tid == -42, containing all flags), and it doesn't have the
             # HAS_SHADOW flag either.  We must move it out of the nursery,
             # into a new nonmovable location.
-            totalsize = size_gc_header + self.get_size(obj)
+            totalsize = size_gc_header + self.shrink_and_get_size(obj)
             self.nursery_surviving_size += raw_malloc_usage(totalsize)
             newhdr = self._malloc_out_of_nursery(totalsize)
             #
diff --git a/rpython/memory/gctypelayout.py b/rpython/memory/gctypelayout.py
--- a/rpython/memory/gctypelayout.py
+++ b/rpython/memory/gctypelayout.py
@@ -241,6 +241,7 @@
             ARRAY = TYPE._flds[TYPE._arrayfld]
             ofs1 = llmemory.offsetof(TYPE, TYPE._arrayfld)
             varinfo.ofstolength = ofs1 + llmemory.ArrayLengthOffset(ARRAY)
+            varinfo.ofstousedlength = varinfo.ofstolength
             varinfo.ofstovar = ofs1 + llmemory.itemoffsetof(ARRAY, 0)
         else:
             assert isinstance(TYPE, lltype.GcArray)
@@ -249,12 +250,12 @@
                 if (isinstance(ARRAY.OF, lltype.Ptr)
                     and ARRAY.OF.TO._gckind == 'gc'):
                     infobits |= T_IS_GCARRAY_OF_GCPTR
-                attrkinds = "length", "length"
+                varinfo.ofstolength = llmemory.ArrayLengthOffset(ARRAY)
+                varinfo.ofstousedlength = varinfo.ofstolength
             else:
-                attrkinds = "allocated_length", "used_length"
-            ALO = llmemory.ArrayLengthOffset
-            varinfo.ofstolength = ALO(ARRAY, attrkind=attrkinds[0])
-            varinfo.ofstousedlength = ALO(ARRAY, attrkind=attrkinds[1])
+                ALO = llmemory.ArrayLengthOffset
+                varinfo.ofstolength = ALO(ARRAY, attrkind="allocated_length")
+                varinfo.ofstousedlength = ALO(ARRAY, attrkind="used_length")
             varinfo.ofstovar = llmemory.itemoffsetof(TYPE, 0)
         assert isinstance(ARRAY, lltype.Array)
         if ARRAY.OF != lltype.Void:
diff --git a/rpython/memory/test/gc_test_base.py 
b/rpython/memory/test/gc_test_base.py
--- a/rpython/memory/test/gc_test_base.py
+++ b/rpython/memory/test/gc_test_base.py
@@ -790,10 +790,10 @@
         if self.SUPPORTS_OVERALLOCATED_ARRAYS:
             EXPECTED_LENGTH = 2
         else:
-            EXPECTED_LENGTH = 10
+            EXPECTED_LENGTH = 3
 
         def fn():
-            a = lltype.malloc(A, 10)
+            a = lltype.malloc(A, 3)
             a.used_length = 2
             s1 = lltype.malloc(S)
             s2 = lltype.malloc(S)
@@ -806,7 +806,6 @@
             assert a.allocated_length == EXPECTED_LENGTH
 
         self.interpret(fn, [])
-
 from rpython.rlib.objectmodel import UnboxedValue
 
 class TaggedBase(object):
diff --git a/rpython/memory/test/test_gctypelayout.py 
b/rpython/memory/test/test_gctypelayout.py
--- a/rpython/memory/test/test_gctypelayout.py
+++ b/rpython/memory/test/test_gctypelayout.py
@@ -136,3 +136,4 @@
     ofs = gcdata.q_varsize_offset_to_used_length(tid)
     assert isinstance(ofs, llmemory.ArrayLengthOffset)
     assert ofs.attrkind == "used_length"
+    assert gcdata.q_is_overallocated_array(tid)
diff --git a/rpython/rtyper/lltypesystem/llarena.py 
b/rpython/rtyper/lltypesystem/llarena.py
--- a/rpython/rtyper/lltypesystem/llarena.py
+++ b/rpython/rtyper/lltypesystem/llarena.py
@@ -35,6 +35,8 @@
         return '<Arena #%d [%d bytes]>' % (self._arena_index, self.nbytes)
 
     def reset(self, zero, start=0, size=None):
+        from rpython.rtyper.lltypesystem import lltype
+        WORD = llmemory.raw_malloc_usage(llmemory.sizeof(lltype.Signed))
         self.check()
         if size is None:
             stop = self.nbytes
@@ -43,11 +45,19 @@
         assert 0 <= start <= stop <= self.nbytes
         for offset, ptr in self.objectptrs.items():
             size = self.objectsizes[offset]
+            clearme = False
             if offset < start:   # object is before the cleared area
                 assert offset + size <= start, "object overlaps cleared area"
             elif offset + size > stop:  # object is after the cleared area
-                assert offset >= stop, "object overlaps cleared area"
+                if offset in (start, start+WORD) and not zero:
+                    # accept non-zeroing reset() with a length that is
+                    # shorter than the actual length, for the gc
+                    clearme = True
+                else:
+                    assert offset >= stop, "object overlaps cleared area"
             else:
+                clearme = True
+            if clearme:
                 obj = ptr._obj
                 _dictdel(Arena.object_arena_location, obj)
                 del self.objectptrs[offset]
diff --git a/rpython/rtyper/lltypesystem/llmemory.py 
b/rpython/rtyper/lltypesystem/llmemory.py
--- a/rpython/rtyper/lltypesystem/llmemory.py
+++ b/rpython/rtyper/lltypesystem/llmemory.py
@@ -300,8 +300,10 @@
         return cast_ptr_to_adr(p)
 
     def raw_memcopy(self, srcadr, dstadr):
-        # should really copy the length field, but we can't
-        pass
+        # should really copy the length field, but we can't.  But still
+        # we need it for the used_length field of overallocated arrays...
+        if self.TYPE._is_overallocated_array():
+            dstadr.ptr.used_length = srcadr.ptr.used_length
 
 
 class ArrayLengthOffset(AddressOffset):
@@ -316,6 +318,16 @@
         self.TYPE = TYPE
         self.attrkind = attrkind
 
+    # special-casing: only for one check in the GC
+    def __eq__(self, other):
+        if self is other:
+            return True
+        if not isinstance(other, ArrayLengthOffset):
+            return False
+        if self.attrkind != other.attrkind:
+            return False
+        raise NotImplementedError
+
     def __repr__(self):
         return '< ArrayLengthOffset %r >' % (self.TYPE,)
 
diff --git a/rpython/rtyper/lltypesystem/lltype.py 
b/rpython/rtyper/lltypesystem/lltype.py
--- a/rpython/rtyper/lltypesystem/lltype.py
+++ b/rpython/rtyper/lltypesystem/lltype.py
@@ -1909,7 +1909,9 @@
                 self.array.shrinklength(value)
         elif self.attrkind == "allocated_length":
             if value != len(self.array.items):
-                raise Exception("can't set allocated_length")
+                if value > len(self.array.items):
+                    raise Exception("can't grow allocated_length in-place")
+                self.array.shrinklength(value)
         elif self.attrkind == "used_length":
             self.array.set_used_length(value)
 
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to