Commits

Alex Gaynor committed 6b75ec7

(fijal, alex): refactor untyped storage (works on llinterp!), and add a gc test

  • Participants
  • Parent commits 9391e81
  • Branches erase-raw-mem

Comments (0)

Files changed (3)

pypy/rlib/rerased_raw.py

 """
 This module supports raw storage of arbitrary data (GC ptr, instance, float,
-int) into a void *.
+int) into a void *.  The creator of the UntypedStorage is responsible for
+making sure that the shape string is cached correctly.
 """
 
 from pypy.annotation import model as annmodel
 from pypy.annotation.bookkeeper import getbookkeeper
+from pypy.rpython.annlowlevel import hlstr, llstr
 from pypy.rpython.extregistry import ExtRegistryEntry
-from pypy.rpython.lltypesystem import rffi, lltype, llmemory
+from pypy.rpython.lltypesystem import rffi, lltype, llmemory, rstr
 from pypy.rpython.rmodel import Repr
 
 
+INT = "i"
+INSTANCE = "o"
+
 class UntypedStorage(object):
-    def __init__(self, n):
-        self.storage = [None] * n
+    def __init__(self, shape):
+        self.storage = [None] * len(shape)
+        self.shape = shape
 
     def getint(self, idx):
+        assert self.shape[idx] == INT
         v = self.storage[idx]
         assert isinstance(v, int)
         return v
 
     def setint(self, idx, v):
+        assert self.shape[idx] == INT
         assert isinstance(v, int)
         self.storage[idx] = v
 
-    # def getfloat(self, idx, f):
-    #     return self.storage[idx]
-
-    # def setfloat(self, idx, f):
-    #     self.storage[idx] = f
-
     def getinstance(self, idx, cls):
         obj = self.storage[idx]
+        assert self.shape[idx] == INSTANCE
         assert isinstance(obj, cls)
         return obj
 
     def setinstance(self, idx, obj):
+        assert self.shape[idx] == INSTANCE
         self.storage[idx] = obj
 
 class UntypedStorageEntry(ExtRegistryEntry):
     _about_ = UntypedStorage
 
-    def compute_result_annotation(self, s_n):
-        assert annmodel.SomeInteger().contains(s_n)
+    def compute_result_annotation(self, s_shape):
+        assert annmodel.SomeString().contains(s_shape)
         return SomeUntypedStorage()
 
     def specialize_call(self, hop):
         assert isinstance(s_obj, annmodel.SomeInstance)
 
 class UntypedStorageRepr(Repr):
-    lowleveltype = lltype.Ptr(lltype.GcArray(lltype.Signed))
+    lowleveltype = lltype.Ptr(lltype.GcStruct("untypedstorage",
+        ("shape", lltype.Ptr(rstr.STR)),
+        ("data", lltype.Array(lltype.Signed, hints={"nolength": True})),
+    ))
 
-    def rtyper_new(self, hop):
-        [v_arg] = hop.inputargs(lltype.Signed)
+    def _read_index(self, hop):
+        v_arr = hop.inputarg(self, arg=0)
+        v_idx = hop.inputarg(lltype.Signed, arg=1)
+        c_name = hop.inputconst(lltype.Void, "data")
         hop.exception_cannot_occur()
-        return hop.gendirectcall(self.ll_new, v_arg)
+        return hop.genop("getinteriorfield", [v_arr, c_name, v_idx],
+                         resulttype=lltype.Signed)
 
-    def rtype_method_getint(self, hop):
-        [v_arr, v_idx] = hop.inputargs(self, lltype.Signed)
-        hop.exception_cannot_occur()
-        return hop.genop("getarrayitem", [v_arr, v_idx], resulttype=lltype.Signed)
-
-    def rtype_method_setint(self, hop):
-        [v_arr, v_idx, v_value] = hop.inputargs(self, lltype.Signed, lltype.Signed)
-        hop.exception_cannot_occur()
-        hop.genop("setarrayitem", [v_arr, v_idx, v_value])
-
-    def rtype_method_getinstance(self, hop):
+    def _write_index(self, hop, v_value):
         v_arr = hop.inputarg(self, arg=0)
         v_idx = hop.inputarg(lltype.Signed, arg=1)
         hop.exception_cannot_occur()
-        v_result = hop.genop("getarrayitem", [v_arr, v_idx], resulttype=lltype.Signed)
+        c_name = hop.inputconst(lltype.Void, "data")
+        hop.genop("setinteriorfield", [v_arr, c_name, v_idx, v_value])
+
+    def rtyper_new(self, hop):
+        [v_shape] = hop.inputargs(rstr.string_repr)
+        hop.exception_cannot_occur()
+        return hop.gendirectcall(self.ll_new, v_shape)
+
+    def rtype_method_getint(self, hop):
+        return self._read_index(hop)
+
+    def rtype_method_setint(self, hop):
+        v_value = hop.inputarg(lltype.Signed, arg=2)
+        self._write_index(hop, v_value)
+
+    def rtype_method_getinstance(self, hop):
+        v_result = self._read_index(hop)
         v_addr = hop.genop("cast_int_to_adr", [v_result], resulttype=llmemory.Address)
         return hop.genop("cast_adr_to_ptr", [v_addr], resulttype=hop.r_result.lowleveltype)
 
     def rtype_method_setinstance(self, hop):
-        [v_arr, v_idx, v_instance] = hop.inputargs(self, lltype.Signed, hop.args_r[2])
-        hop.exception_cannot_occur()
-        v_addr = hop.genop("cast_ptr_to_adr", [v_instance], resulttype=llmemory.Address)
-        v_result = hop.genop("cast_adr_to_int", [v_addr, hop.inputconst(lltype.Void, "symbolic")], resulttype=lltype.Signed)
-        hop.genop("setarrayitem", [v_arr, v_idx, v_result])
+        v_instance = hop.inputarg(hop.args_r[2], arg=2)
+
+        v_addr = hop.genop("cast_ptr_to_adr", [v_instance],
+                           resulttype=llmemory.Address)
+        v_value = hop.genop("cast_adr_to_int",
+                            [v_addr, hop.inputconst(lltype.Void, "symbolic")],
+                            resulttype=lltype.Signed)
+        self._write_index(hop, v_value)
 
     @classmethod
-    def ll_new(cls, size):
-        return lltype.malloc(cls.lowleveltype.TO, size)
+    def ll_new(cls, shape):
+        obj = lltype.malloc(cls.lowleveltype.TO, len(shape.chars))
+        obj.shape = shape
+        return obj

pypy/rlib/test/test_rerased_raw.py

 
 
 def test_direct_int():
-    storage = rerased_raw.UntypedStorage(2)
+    storage = rerased_raw.UntypedStorage("ii")
 
     storage.setint(0, 2)
     assert storage.getint(0) == 2
         def __init__(self, value):
             self.value = value
 
-    storage = rerased_raw.UntypedStorage(1)
+    storage = rerased_raw.UntypedStorage("o")
     storage.setinstance(0, A(4))
 
     assert storage.getinstance(0, A).value == 4
 class TestRerasedRawLLType(LLRtypeMixin, BaseRtypingTest):
     def test_int(self):
         def f(x):
-            storage = rerased_raw.UntypedStorage(1)
+            storage = rerased_raw.UntypedStorage("i")
             storage.setint(0, x)
             return storage.getint(0)
 
                 self.v = v
 
         def f(x):
-            storage = rerased_raw.UntypedStorage(1)
+            storage = rerased_raw.UntypedStorage("o")
             storage.setinstance(0, A(x))
             return storage.getinstance(0, A).v
 
 
         def f(x):
             try:
-                storage = rerased_raw.UntypedStorage(2)
+                storage = rerased_raw.UntypedStorage("io")
                 storage.setint(0, x)
                 value1 = storage.getint(0)
                 storage.setinstance(1, A(x))
 
         res = self.interpret(f, [4])
         assert res == 8
+
+    def test_union(self):
+        def f(x, v):
+            if x:
+                storage = rerased_raw.UntypedStorage("i")
+            else:
+                storage = rerased_raw.UntypedStorage("ii")
+            storage.setint(0, v)
+            return storage.getint(0)
+
+        res = self.interpret(f, [True, 15])
+        assert res == 15

pypy/rpython/memory/test/test_gc.py

 from pypy.rpython.test.test_llinterp import get_interpreter
 from pypy.rpython.lltypesystem import lltype
 from pypy.rpython.lltypesystem.lloperation import llop
-from pypy.rlib.objectmodel import we_are_translated
-from pypy.rlib.objectmodel import compute_unique_id
+from pypy.rlib.objectmodel import we_are_translated, compute_unique_id
 from pypy.rlib import rgc
+from pypy.rlib.rerased_raw import UntypedStorage
 from pypy.rlib.rstring import StringBuilder
 from pypy.rlib.rarithmetic import LONG_BIT
 
         for i in range(1, 15):
             res = self.interpret(append_to_list, [i, i - 1])
             assert res == i - 1 # crashes if constants are not considered roots
-            
+
     def test_string_concatenation(self):
         #curr = simulator.current_size
         def concat(j):
         res = self.interpret(fn, [])
         assert res == ord('y')
 
+    def test_untypedstorage(self):
+        class A(object):
+            def __init__(self, v):
+                self.v = v
+
+        def fn(v):
+            s = UntypedStorage("io")
+            s.setint(0, v)
+            s.setinstance(1, A(v))
+            rgc.collect()
+            return s.getint(0) + s.getinstance(1, A).v
+
+        res = self.interpret(fn, [10])
+        assert res == 20
+
+
 from pypy.rlib.objectmodel import UnboxedValue
 
 class TaggedBase(object):