Commits

Antonio Cuni committed 493bb1d

bah, it might happen that we have two arraydescrs which are equal but not identical: apply the optimization also in those cases

  • Participants
  • Parent commits 636ac5d
  • Branches virtual-raw-mallocs

Comments (0)

Files changed (4)

File pypy/jit/metainterp/optimizeopt/rawbuffer.py

     pass
 
 class RawBuffer(object):
-    def __init__(self):
+    def __init__(self, cpu):
         # the following lists represents the writes in the buffer: values[i]
         # is the value of length lengths[i] stored at offset[i].
         #
         # the invariant is that they are ordered by offset, and that
         # offset[i]+length[i] <= offset[i+1], i.e. that the writes never
         # overlaps
+        self.cpu = cpu
         self.offsets = []
         self.lengths = []
         self.descrs = []
         """
         return zip(self.offsets, self.lengths, self.descrs, self.values)
 
+    def _descrs_are_compatible(self, d1, d2):
+        # two arraydescrs are compatible if they have the same basesize,
+        # itemsize and sign, even if they are not identical
+        unpack = self.cpu.unpack_arraydescr_size
+        return unpack(d1) == unpack(d2)
+
     def write_value(self, offset, length, descr, value):
         i = 0
         N = len(self.offsets)
         while i < N:
             if self.offsets[i] == offset:
-                if length != self.lengths[i] or descr != self.descrs[i]:
+                if (length != self.lengths[i] or not
+                    self._descrs_are_compatible(descr, self.descrs[i])):
                     # in theory we could add support for the cases in which
                     # the length or descr is different, but I don't think we
                     # need it in practice
         N = len(self.offsets)
         while i < N:
             if self.offsets[i] == offset:
-                if length != self.lengths[i] or descr != self.descrs[i]:
+                if (length != self.lengths[i] or
+                    not self._descrs_are_compatible(descr, self.descrs[i])):
                     raise InvalidRawRead
                 return self.values[i]
             i += 1

File pypy/jit/metainterp/optimizeopt/test/test_rawbuffer.py

 from pypy.jit.metainterp.optimizeopt.rawbuffer import (InvalidRawWrite,
                                                        InvalidRawRead, RawBuffer)
 
+class FakeCPU(object):
+    def unpack_arraydescr_size(self, descr):
+        return descr, 'foo', 'bar'
+
 def test_write_value():
-    buf = RawBuffer()
+    buf = RawBuffer(FakeCPU())
     buf.write_value(8, 4, 'descr3', 'three')
     buf.write_value(0, 4, 'descr1', 'one')
     buf.write_value(4, 2, 'descr2', 'two')
     #
 
 def test_write_value_update():
-    buf = RawBuffer()
+    buf = RawBuffer(FakeCPU())
     buf.write_value(0, 4, 'descr', 'one')
     buf.write_value(4, 2, 'descr', 'two')
     buf.write_value(0, 4, 'descr', 'ONE')
         ]
 
 def test_write_value_invalid_length():
-    buf = RawBuffer()
+    buf = RawBuffer(FakeCPU())
     buf.write_value(0, 4, 'descr1', 'one')
     with py.test.raises(InvalidRawWrite):
         buf.write_value(0, 5, 'descr1', 'two')
 
     
 def test_write_value_overlapping_next():
-    buf = RawBuffer()
+    buf = RawBuffer(FakeCPU())
     buf.write_value(0, 4, 'descr', 'one')
     buf.write_value(6, 4, 'descr', 'two')
     with py.test.raises(InvalidRawWrite):
         buf.write_value(4, 4, 'descr', 'three')
 
 def test_write_value_overlapping_prev():
-    buf = RawBuffer()
+    buf = RawBuffer(FakeCPU())
     buf.write_value(0, 4, 'descr', 'one')
     with py.test.raises(InvalidRawWrite):
         buf.write_value(2, 1, 'descr', 'two')
 
 def test_read_value():
-    buf = RawBuffer()
+    buf = RawBuffer(FakeCPU())
     buf.write_value(0, 4, 'descr', 'one')
     buf.write_value(4, 4, 'descr', 'two')
     assert buf.read_value(0, 4, 'descr') == 'one'
     with py.test.raises(InvalidRawRead):
         buf.read_value(0, 4, 'another descr')
 
+def test_unpack_descrs():
+    ArrayS_8_1 = object()
+    ArrayS_8_2 = object()
+    ArrayU_8 = object()
+
+    class FakeCPU(object):
+        def unpack_arraydescr_size(self, descr):
+            if descr in (ArrayS_8_1, ArrayS_8_2):
+                return 0, 8, True
+            return 0, 8, False
+
+    buf = RawBuffer(FakeCPU())
+    buf.write_value(0, 4, ArrayS_8_1, 'one')
+    assert buf.read_value(0, 4, ArrayS_8_1) == 'one'
+    assert buf.read_value(0, 4, ArrayS_8_2) == 'one' # with a non-identical descr
+    #
+    buf.write_value(0, 4, ArrayS_8_2, 'two') # with a non-identical descr
+    assert buf.read_value(0, 4, ArrayS_8_1) == 'two'
+    #
+    with py.test.raises(InvalidRawRead):
+        buf.read_value(0, 4, ArrayU_8)
+    with py.test.raises(InvalidRawWrite):
+        buf.write_value(0, 4, ArrayU_8, 'three')

File pypy/jit/metainterp/optimizeopt/virtualize.py

 
 class VRawBufferValue(AbstractVArrayValue):
 
-    def __init__(self, size, keybox, source_op):
+    def __init__(self, cpu, size, keybox, source_op):
         AbstractVirtualValue.__init__(self, keybox, source_op)
         # note that size is unused, because we assume that the buffer is big
         # enough to write/read everything we need. If it's not, it's undefined
         # behavior anyway, although in theory we could probably detect such
         # cases here
         self.size = size
-        self.buffer = RawBuffer()
+        self.buffer = RawBuffer(cpu)
 
     def getlength(self):
         return len(self.buffer.values)
         return vvalue
 
     def make_virtual_raw_memory(self, size, box, source_op):
-        vvalue = VRawBufferValue(size, box, source_op)
+        vvalue = VRawBufferValue(self.optimizer.cpu, size, box, source_op)
         self.make_equal_to(box, vvalue)
         return vvalue
 

File pypy/jit/metainterp/pyjitpl.py

         box_exchange_buffer = op.getarg(3)
         self.history.operations.pop()
         arg_boxes = []
+
         for i in range(cif_description.nargs):
             kind, descr = get_arg_descr(self.cpu, cif_description.atypes[i])
             if kind == 'i':