Author: Maciej Fijalkowski <[email protected]>
Branch: array-overallocation-in-nursery
Changeset: r67494:2cd6bc0f2b06
Date: 2013-10-22 11:30 +0200
http://bitbucket.org/pypy/pypy/changeset/2cd6bc0f2b06/
Log: (fijal, arigo) The goal is to support overallocated arrays more
directly in the GC. The lltype simulation part
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
@@ -1,6 +1,6 @@
from rpython.rlib.rarithmetic import (r_int, r_uint, intmask, r_singlefloat,
- r_ulonglong, r_longlong, r_longfloat,
r_longlonglong,
- base_int, normalizedinttype, longlongmask,
longlonglongmask)
+ r_ulonglong, r_longlong, r_longfloat, r_longlonglong, base_int,
+ normalizedinttype, longlongmask, longlonglongmask)
from rpython.rlib.objectmodel import Symbolic
from rpython.tool.identity_dict import identity_dict
from rpython.tool import leakfinder
@@ -193,6 +193,9 @@
def _inline_is_varsize(self, last):
raise TypeError, "%r cannot be inlined in structure" % self
+ def _is_overallocated_array(self):
+ return False
+
def _install_extras(self, adtmeths={}, hints={}):
self._adtmeths = frozendict(adtmeths)
self._hints = frozendict(hints)
@@ -435,6 +438,11 @@
self.OF._inline_is_varsize(False)
self._install_extras(**kwds)
+ if self._is_overallocated_array():
+ assert self._gckind == 'gc', "no support for raw overallocated
arrays"
+
+ def _is_overallocated_array(self):
+ return self._hints.get('overallocated', False)
def _inline_is_varsize(self, last):
if not last:
@@ -481,7 +489,6 @@
def _inline_is_varsize(self, last):
raise TypeError("cannot inline a GC array inside a structure")
-
class FixedSizeArray(Struct):
# behaves more or less like a Struct with fields item0, item1, ...
# but also supports __getitem__(), __setitem__(), __len__().
@@ -1160,6 +1167,11 @@
if field_name in self._T._flds:
o = self._obj._getattr(field_name)
return self._expose(field_name, o)
+ if self._T._is_overallocated_array():
+ if field_name == 'allocated_length':
+ return self._obj.getlength()
+ elif field_name == 'used_length':
+ return self._obj.used_len
try:
return self._lookup_adtmeth(field_name)
except AttributeError:
@@ -1178,6 +1190,16 @@
"expects %r\n"
" got %r" % (self._T, field_name, T1,
T2))
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
+ return
raise AttributeError("%r instance has no field %r" % (self._T,
field_name))
@@ -1218,7 +1240,8 @@
def __len__(self):
if isinstance(self._T, (Array, FixedSizeArray)):
- if self._T._hints.get('nolength', False):
+ if (self._T._hints.get('nolength', False) or
+ self._T._hints.get('overallocated', False)):
raise TypeError("%r instance has no length attribute" %
(self._T,))
return self._obj.getlength()
@@ -1652,14 +1675,14 @@
class _array(_parentable):
_kind = "array"
- __slots__ = ('items',)
-
def __init__(self, TYPE, n, initialization=None, parent=None,
parentindex=None):
if not is_valid_int(n):
raise TypeError, "array length must be an int"
if n < 0:
raise ValueError, "negative array length"
_parentable.__init__(self, TYPE)
+ if TYPE._is_overallocated_array():
+ self.used_len = 0
myrange = self._check_range(n)
self.items = [TYPE.OF._allocate(initialization=initialization,
parent=self, parentindex=j)
@@ -1709,7 +1732,10 @@
del self.items[newlength:]
def getbounds(self):
- stop = len(self.items)
+ if self._TYPE._is_overallocated_array():
+ stop = self.used_len
+ else:
+ stop = len(self.items)
return 0, stop
def getitem(self, index, uninitialized_ok=False):
@@ -1722,7 +1748,6 @@
assert typeOf(value) == self._TYPE.OF
self.items[index] = value
-assert not '__dict__' in dir(_array)
assert not '__dict__' in dir(_struct)
diff --git a/rpython/rtyper/lltypesystem/test/test_lltype.py
b/rpython/rtyper/lltypesystem/test/test_lltype.py
--- a/rpython/rtyper/lltypesystem/test/test_lltype.py
+++ b/rpython/rtyper/lltypesystem/test/test_lltype.py
@@ -235,7 +235,7 @@
del p1
import gc
gc.collect()
- py.test.raises(RuntimeError, "p1_5.v")
+ py.test.raises(RuntimeError, "p1_5.v")
def test_examples():
A1 = GcArray(('v', Signed))
@@ -388,11 +388,11 @@
s.x = 1
def type_info_S(p):
return getRuntimeTypeInfo(S)
- qp = functionptr(FuncType([Ptr(S)], Ptr(RuntimeTypeInfo)),
- "type_info_S",
+ qp = functionptr(FuncType([Ptr(S)], Ptr(RuntimeTypeInfo)),
+ "type_info_S",
_callable=type_info_S)
- dp = functionptr(FuncType([Ptr(S)], Void),
- "destructor_funcptr",
+ dp = functionptr(FuncType([Ptr(S)], Void),
+ "destructor_funcptr",
_callable=f)
pinf0 = attachRuntimeTypeInfo(S, qp, destrptr=dp)
assert pinf0._obj.about == S
@@ -422,8 +422,8 @@
return getRuntimeTypeInfo(S)
else:
return getRuntimeTypeInfo(S1)
- fp = functionptr(FuncType([Ptr(S)], Ptr(RuntimeTypeInfo)),
- "dynamic_type_info_S",
+ fp = functionptr(FuncType([Ptr(S)], Ptr(RuntimeTypeInfo)),
+ "dynamic_type_info_S",
_callable=dynamic_type_info_S)
attachRuntimeTypeInfo(S, fp)
assert s.x == 0
@@ -434,7 +434,7 @@
py.test.raises(RuntimeError, "runtime_type_info(s1.sub)")
s1.sub.x = 1
assert runtime_type_info(s1.sub) == getRuntimeTypeInfo(S1)
-
+
def test_flavor_malloc():
def isweak(p, T):
return p._weak and typeOf(p).TO == T
@@ -450,7 +450,7 @@
p = malloc(T, flavor="gc")
assert typeOf(p).TO == T
assert not isweak(p, T)
-
+
def test_opaque():
O = OpaqueType('O')
p1 = opaqueptr(O, 'p1', hello="world")
@@ -520,8 +520,8 @@
def test_adtmeths():
def h_newstruct():
return malloc(S)
-
- S = GcStruct('s', ('x', Signed),
+
+ S = GcStruct('s', ('x', Signed),
adtmeths={"h_newstruct": h_newstruct})
s = S.h_newstruct()
@@ -553,15 +553,15 @@
def h_newstruct(S):
return malloc(S)
h_newstruct = typeMethod(h_newstruct)
-
- S = GcStruct('s', ('x', Signed),
+
+ S = GcStruct('s', ('x', Signed),
adtmeths={"h_newstruct": h_newstruct})
s = S.h_newstruct()
assert typeOf(s) == Ptr(S)
- Sprime = GcStruct('s', ('x', Signed),
+ Sprime = GcStruct('s', ('x', Signed),
adtmeths={"h_newstruct": h_newstruct})
assert S == Sprime
@@ -592,7 +592,7 @@
PA = Ptr(A)
a = malloc(A, 2)
assert cast_pointer(PA, a) == a
-
+
def test_array_with_no_length():
A = GcArray(Signed, hints={'nolength': True})
a = malloc(A, 10)
@@ -604,7 +604,7 @@
s = malloc(GcS)
s.x = 1
assert list(dissect_ll_instance(s)) == [(Ptr(GcS), s), (GcS, s._obj),
(Signed, 1)]
-
+
A = GcArray(('x', Signed))
a = malloc(A, 10)
for i in range(10):
@@ -808,6 +808,21 @@
assert F.RESULT == Signed
assert F.ARGS == (Signed,)
+def test_overallocated_array():
+ A = GcArray(lltype.Signed, hints={'overallocated': True})
+ a = lltype.malloc(A, 10)
+ py.test.raises(IndexError, "a[1]")
+ py.test.raises(TypeError, len, a)
+ assert a.allocated_length == 10
+ assert a.used_length == 0
+ a.used_length = 5
+ py.test.raises(ValueError, "a.used_length = 13")
+ a[3] = 42
+ assert a[3] == 42
+ a.used_length = 1
+ py.test.raises(IndexError, "a[3]")
+ py.test.raises(IndexError, "a[3] = 43")
+
class TestTrackAllocation:
def test_automatic_tracking(self):
# calls to start_tracking_allocations/stop_tracking_allocations
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit