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

Reply via email to