[pypy-commit] pypy array-overallocation-in-nursery: (fijal around, arigo)

arigo noreply at buildbot.pypy.org
Tue Oct 22 12:05:13 CEST 2013


Author: Armin Rigo <arigo at tunes.org>
Branch: array-overallocation-in-nursery
Changeset: r67498:75ab419638af
Date: 2013-10-22 12:04 +0200
http://bitbucket.org/pypy/pypy/changeset/75ab419638af/

Log:	(fijal around, arigo)

	Support rtyping the operations specific to overallocated arrays.

diff --git a/rpython/rtyper/llinterp.py b/rpython/rtyper/llinterp.py
--- a/rpython/rtyper/llinterp.py
+++ b/rpython/rtyper/llinterp.py
@@ -624,6 +624,19 @@
         if ITEMTYPE is not lltype.Void:
             array[index] = item
 
+    def op_getarrayallocatedlength(self, obj):
+        checkptr(obj)
+        return obj.allocated_length
+
+    def op_getarrayusedlength(self, obj):
+        checkptr(obj)
+        return obj.used_length
+
+    def op_setarrayusedlength(self, obj, nlen):
+        checkptr(obj)
+        assert isinstance(nlen, int)
+        obj.used_length = nlen
+
     def perform_call(self, f, ARGS, args):
         fobj = self.llinterpreter.typer.type_system.deref(f)
         has_callable = getattr(fobj, '_callable', None) is not None
diff --git a/rpython/rtyper/lltypesystem/lloperation.py b/rpython/rtyper/lltypesystem/lloperation.py
--- a/rpython/rtyper/lltypesystem/lloperation.py
+++ b/rpython/rtyper/lltypesystem/lloperation.py
@@ -386,6 +386,9 @@
     'bare_setfield':        LLOp(),
     'setarrayitem':         LLOp(),
     'bare_setarrayitem':    LLOp(),
+    'getarrayallocatedlength': LLOp(sideeffects=False), # over-allocated arrays
+    'getarrayusedlength':   LLOp(sideeffects=False),    # over-allocated arrays
+    'setarrayusedlength':   LLOp(),                     # over-allocated arrays
     'cast_pointer':         LLOp(canfold=True),
     'ptr_eq':               LLOp(canfold=True),
     'ptr_ne':               LLOp(canfold=True),
diff --git a/rpython/rtyper/rptr.py b/rpython/rtyper/rptr.py
--- a/rpython/rtyper/rptr.py
+++ b/rpython/rtyper/rptr.py
@@ -47,6 +47,16 @@
         else:
             assert hop.s_result.is_constant()
             return hop.inputconst(hop.r_result, hop.s_result.const)
+        if self.lowleveltype.TO._is_overallocated_array():
+            v_self = hop.inputarg(self, arg=0)
+            if attr == 'allocated_length':
+                return hop.genop('getarrayallocatedlength', [v_self],
+                                 resulttype = lltype.Signed)
+            elif attr == 'used_length':
+                return hop.genop('getarrayusedlength', [v_self],
+                                 resulttype = lltype.Signed)
+            else:
+                raise TyperError("getattr(overallocated_array, %r)" % (attr,))
         assert attr in self.lowleveltype.TO._flds # check that the field exists
         FIELD_TYPE = getattr(self.lowleveltype.TO, attr)
         if isinstance(FIELD_TYPE, lltype.ContainerType):
@@ -65,6 +75,14 @@
 
     def rtype_setattr(self, hop):
         attr = hop.args_s[1].const
+        if self.lowleveltype.TO._is_overallocated_array():
+            if attr == 'used_length':
+                v_self = hop.inputarg(self, arg=0)
+                v_length = hop.inputarg(lltype.Signed, arg=2)
+                hop.genop('setarrayusedlength', [v_self, v_length])
+                return
+            else:
+                raise TyperError("setattr(overallocated_array, %r)" % (attr,))
         FIELD_TYPE = getattr(self.lowleveltype.TO, attr)
         assert not isinstance(FIELD_TYPE, lltype.ContainerType)
         vlist = hop.inputargs(self, lltype.Void, hop.args_r[2])
diff --git a/rpython/rtyper/test/test_llann.py b/rpython/rtyper/test/test_llann.py
--- a/rpython/rtyper/test/test_llann.py
+++ b/rpython/rtyper/test/test_llann.py
@@ -509,3 +509,18 @@
     assert res is True
     res = interpret(f, [25, 10])
     assert res is True
+
+
+def test_overallocated_array():
+    A = GcArray(Signed, hints={'overallocated': True})
+
+    def f():
+        a = malloc(A, 10)
+        a.used_length = 5
+        a[3] = 42
+        assert a[3] == 42
+        return a.used_length + (a.allocated_length * 100)
+
+    assert f() == 1005
+    res = interpret(f, [])
+    assert res == 1005


More information about the pypy-commit mailing list