Commits

Antonio Cuni committed 1f2cb47

implement 'slicing' of a rawbuffer: we can call int_add on it and still have it virtual

Comments (0)

Files changed (2)

pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py

         """
         self.optimize_loop(ops, expected)
 
+    def test_virtual_raw_slice(self):
+        ops = """
+        [i0, i1]
+        i2 = call('malloc', 10, descr=raw_malloc_descr)
+        setarrayitem_raw(i2, 0, 42, descr=rawarraydescr_char)
+        i3 = int_add(i2, 1) # get a slice of the original buffer
+        setarrayitem_raw(i3, 0, 4242, descr=rawarraydescr) # write to the slice
+        i4 = getarrayitem_raw(i2, 0, descr=rawarraydescr_char)
+        i5 = int_add(i2, 1)
+        i6 = getarrayitem_raw(i5, 0, descr=rawarraydescr)
+        call('free', i2, descr=raw_free_descr)
+        jump(i0, i1)
+        """
+        expected = """
+        [i0, i1]
+        jump(i0, i1)
+        """
+        self.optimize_loop(ops, expected)
+
+
     def test_duplicate_getfield_1(self):
         ops = """
         [p1, p2]

pypy/jit/metainterp/optimizeopt/virtualize.py

         return modifier.make_varraystruct(self.arraydescr, self._get_list_of_descrs())
 
 
-class VirtualRawMemoryValue(AbstractVirtualValue):
+class VirtualRawBufferValue(AbstractVirtualValue):
 
-    def __init__(self, cpu, size, keybox, source_op):
+    def __init__(self, size, keybox, source_op):
         AbstractVirtualValue.__init__(self, keybox, source_op)
-        self.cpu = cpu
         # 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
         return self.buffer.read_value(offset, length, descr)
 
 
+class VirtualRawSliceValue(AbstractVirtualValue):
+
+    def __init__(self, rawbuffer_value, offset, keybox, source_op):
+        AbstractVirtualValue.__init__(self, keybox, source_op)
+        self.rawbuffer_value = rawbuffer_value
+        self.offset = offset
+
+    def _really_force(self, optforce):
+        import pdb;pdb.set_trace()
+
+    def setitem_raw(self, offset, length, descr, value):
+        self.rawbuffer_value.setitem_raw(self.offset+offset, length, descr, value)
+
+    def getitem_raw(self, offset, length, descr):
+        return self.rawbuffer_value.getitem_raw(self.offset+offset, length, descr)
+
 class OptVirtualize(optimizer.Optimization):
     "Virtualize objects until they escape."
 
         return vvalue
 
     def make_virtual_raw_memory(self, size, box, source_op):
-        vvalue = VirtualRawMemoryValue(self.optimizer.cpu, size, box, source_op)
+        vvalue = VirtualRawBufferValue(size, box, source_op)
+        self.make_equal_to(box, vvalue)
+        return vvalue
+
+    def make_virtual_raw_slice(self, rawbuffer_value, offset, box, source_op):
+        vvalue = VirtualRawSliceValue(rawbuffer_value, offset, box, source_op)
         self.make_equal_to(box, vvalue)
         return vvalue
 
             return
         self.emit_operation(op)
 
+    def optimize_INT_ADD(self, op):
+        value = self.getvalue(op.getarg(0))
+        offsetbox = self.get_constant_box(op.getarg(1))
+        if value.is_virtual() and offsetbox is not None:
+            offset = offsetbox.getint()
+            if isinstance(value, VirtualRawBufferValue):
+                self.make_virtual_raw_slice(value, offset, op.result, op)
+                return
+        self.emit_operation(op)
+
     def optimize_ARRAYLEN_GC(self, op):
         value = self.getvalue(op.getarg(0))
         if value.is_virtual():