Author: Armin Rigo <[email protected]>
Branch: array-overallocation-in-nursery
Changeset: r67503:0422d725e21c
Date: 2013-10-22 12:45 +0200
http://bitbucket.org/pypy/pypy/changeset/0422d725e21c/
Log: (fijal, arigo)
Support llmemory.ArrayLengthOffset to point to the two kinds of
lengths
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
@@ -306,8 +306,15 @@
class ArrayLengthOffset(AddressOffset):
- def __init__(self, TYPE):
+ def __init__(self, TYPE, attrkind="length"):
+ assert isinstance(TYPE, lltype.Array)
+ assert not TYPE._hints.get('nolength', False)
+ if attrkind == "length":
+ assert not TYPE._is_overallocated_array()
+ else:
+ assert TYPE._is_overallocated_array()
self.TYPE = TYPE
+ self.attrkind = attrkind
def __repr__(self):
return '< ArrayLengthOffset %r >' % (self.TYPE,)
@@ -317,7 +324,8 @@
def ref(self, arrayptr):
assert array_type_match(lltype.typeOf(arrayptr).TO, self.TYPE)
- return lltype._arraylenref._makeptr(arrayptr._obj, arrayptr._solid)
+ return lltype._arraylenref._makeptr(arrayptr._obj, arrayptr._solid,
+ self.attrkind)
class GCHeaderOffset(AddressOffset):
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
@@ -1192,13 +1192,7 @@
return
if self._T._is_overallocated_array():
if field_name == 'used_length':
- if val > self._obj.getlength():
- raise ValueError("overallocated array size is %s, trying "
- "to set used size to %s" %
- (self._obj.getlength(), val))
- for i in range(val, self._obj.used_len):
- self._obj.items[i] = self._T.OF._allocate('malloc')
- self._obj.used_len = val
+ self._obj.set_used_length(val)
return
raise AttributeError("%r instance has no field %r" % (self._T,
field_name))
@@ -1755,6 +1749,16 @@
assert typeOf(value) == self._TYPE.OF
self.items[index] = value
+ def set_used_length(self, val):
+ assert self._TYPE._is_overallocated_array()
+ if val > self.getlength():
+ raise ValueError("overallocated array size is %s, trying "
+ "to set used size to %s" %
+ (self.getlength(), val))
+ for i in range(val, self.used_len):
+ self.items[i] = self._TYPE.OF._allocate('malloc')
+ self.used_len = val
+
assert not '__dict__' in dir(_struct)
@@ -1868,12 +1872,18 @@
Only used internally by llmemory to implement ArrayLengthOffset.
"""
_kind = "arraylenptr"
- _cache = weakref.WeakKeyDictionary() # array -> _arraylenref
+ _cache = {
+ "length": weakref.WeakKeyDictionary(), # array -> _arraylenref
+ "allocated_length": weakref.WeakKeyDictionary(),
+ "used_length": weakref.WeakKeyDictionary(),
+ }
- def __init__(self, array):
+ def __init__(self, array, attrkind):
TYPE = FixedSizeArray(Signed, 1)
_parentable.__init__(self, TYPE)
self.array = array
+ self.attrkind = attrkind
+ assert attrkind in self._cache
def getlength(self):
return 1
@@ -1883,23 +1893,34 @@
def getitem(self, index, uninitialized_ok=False):
assert index == 0
- return self.array.getlength()
+ if self.attrkind == "length":
+ return self.array.getlength()
+ elif self.attrkind == "allocated_length":
+ return len(self.array.items)
+ elif self.attrkind == "used_length":
+ return self.array.used_len
def setitem(self, index, value):
assert index == 0
- if value != self.array.getlength():
- if value > self.array.getlength():
- raise Exception("can't grow an array in-place")
- self.array.shrinklength(value)
+ if self.attrkind == "length":
+ if value != self.array.getlength():
+ if value > self.array.getlength():
+ raise Exception("can't grow an array in-place")
+ self.array.shrinklength(value)
+ elif self.attrkind == "allocated_length":
+ raise Exception("can't set allocated_length")
+ elif self.attrkind == "used_length":
+ self.array.set_used_length(value)
- def _makeptr(array, solid=False):
+ @staticmethod
+ def _makeptr(array, solid=False, attrkind="length"):
+ cache = _arraylenref._cache[attrkind]
try:
- lenref = _arraylenref._cache[array]
+ lenref = cache[array]
except KeyError:
- lenref = _arraylenref(array)
- _arraylenref._cache[array] = lenref
+ lenref = _arraylenref(array, attrkind)
+ cache[array] = lenref
return _ptr(Ptr(lenref._TYPE), lenref, solid)
- _makeptr = staticmethod(_makeptr)
def _getid(self):
raise NotImplementedError('_arraylenref._getid()')
diff --git a/rpython/rtyper/lltypesystem/test/test_llmemory.py
b/rpython/rtyper/lltypesystem/test/test_llmemory.py
--- a/rpython/rtyper/lltypesystem/test/test_llmemory.py
+++ b/rpython/rtyper/lltypesystem/test/test_llmemory.py
@@ -649,3 +649,16 @@
#assert cast_int_to_adr(i) == adr -- depends on ll2ctypes details
i = cast_adr_to_int(NULL, mode="forced")
assert is_valid_int(i) and i == 0
+
+def test_overallocated_array():
+ A = lltype.GcArray(lltype.Signed, hints={'overallocated': True})
+ a = lltype.malloc(A, 10)
+ adr = cast_ptr_to_adr(a)
+ py.test.raises(AssertionError, ArrayLengthOffset, A)
+ length_adr = adr + ArrayLengthOffset(A, "allocated_length")
+ assert length_adr.signed[0] == 10
+ length_adr = adr + ArrayLengthOffset(A, "used_length")
+ assert length_adr.signed[0] == 0
+ #
+ length_adr.signed[0] = 2
+ assert a.used_length == 2
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit