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