[pypy-commit] pypy optresult: start fighting with raw buffers

fijal noreply at buildbot.pypy.org
Wed Jun 3 11:02:51 CEST 2015


Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: optresult
Changeset: r77809:fc54d02f8b1c
Date: 2015-06-03 11:02 +0200
http://bitbucket.org/pypy/pypy/changeset/fc54d02f8b1c/

Log:	start fighting with raw buffers

diff --git a/rpython/jit/metainterp/optimizeopt/info.py b/rpython/jit/metainterp/optimizeopt/info.py
--- a/rpython/jit/metainterp/optimizeopt/info.py
+++ b/rpython/jit/metainterp/optimizeopt/info.py
@@ -4,6 +4,7 @@
      rop
 from rpython.jit.metainterp.history import ConstInt, Const
 from rpython.rtyper.lltypesystem import lltype
+from rpython.jit.metainterp.optimizeopt.rawbuffer import RawBuffer, InvalidRawOperation
 
 
 INFO_NULL = 0
@@ -141,11 +142,10 @@
                                          for box in self._fields])
         for i in range(len(lst)):
             op = self._fields[i]
-            if op and op.type == 'r':
-                op = op.get_box_replacement()
-                fieldinfo = optimizer.getptrinfo(op)
-                if fieldinfo and fieldinfo.is_virtual():
-                    fieldinfo.visitor_walk_recursive(op, visitor, optimizer)
+            op = op.get_box_replacement()
+            fieldinfo = optimizer.getptrinfo(op)
+            if fieldinfo and fieldinfo.is_virtual():
+                fieldinfo.visitor_walk_recursive(op, visitor, optimizer)
 
 class InstancePtrInfo(AbstractStructPtrInfo):
     _attrs_ = ('_known_class',)
@@ -174,8 +174,85 @@
         assert self.is_virtual()
         return visitor.visit_vstruct(self.vdescr, fielddescrs)
 
-class RawStructPtrInfo(StructPtrInfo):
-    pass
+class AbstractRawPtrInfo(AbstractVirtualPtrInfo):
+    def visitor_walk_recursive(self, op, visitor, optimizer):
+        xxx
+        box = self.rawbuffer_value.get_key_box()
+        visitor.register_virtual_fields(self.keybox, [box])
+        self.rawbuffer_value.visitor_walk_recursive(visitor)
+
+    @specialize.argtype(1)
+    def visitor_dispatch_virtual_type(self, visitor):
+        yyy
+        return visitor.visit_vrawslice(self.offset)    
+
+class RawBufferPtrInfo(AbstractRawPtrInfo):
+    buffer = None
+    
+    def __init__(self, cpu, size=-1):
+        self.size = size
+        if self.size != -1:
+            self.buffer = RawBuffer(cpu, None)
+
+    def getitem_raw(self, offset, itemsize, descr):
+        if not self.is_virtual():
+            raise InvalidRawOperation
+            # see 'test_virtual_raw_buffer_forced_but_slice_not_forced'
+            # for the test above: it's not enough to check is_virtual()
+            # on the original object, because it might be a VRawSliceValue
+            # instead.  If it is a virtual one, then we'll reach here anway.
+        return self.buffer.read_value(offset, itemsize, descr)
+
+    def setitem_raw(self, offset, itemsize, descr, itemop):
+        if not self.is_virtual():
+            raise InvalidRawOperation
+        self.buffer.write_value(offset, itemsize, descr, itemop)
+
+    def is_virtual(self):
+        return self.size != -1
+
+    def _force_elements(self, op, optforce, descr):
+        xxx
+
+    def visitor_walk_recursive(self, op, visitor, optimizer):
+        itemboxes = self.buffer.values
+        visitor.register_virtual_fields(op, itemboxes)
+        #for itembox in itemboxes:
+        #    xxx
+        #    itemvalue = self.get_item_value(i)
+        #    if itemvalue is not None:
+        #        itemvalue.visitor_walk_recursive(visitor)
+
+    @specialize.argtype(1)
+    def visitor_dispatch_virtual_type(self, visitor):
+        return visitor.visit_vrawbuffer(self.size,
+                                        self.buffer.offsets[:],
+                                        self.buffer.descrs[:])
+
+class RawStructPtrInfo(AbstractRawPtrInfo):
+    def __init__(self):
+        import pdb
+        pdb.set_trace()
+    
+    def _force_elements(self, op, optforce, descr):
+        xxx
+
+class RawSlicePtrInfo(AbstractRawPtrInfo):
+    def __init__(self, offset, parent):
+        self.offset = offset
+        self.parent = parent
+
+    def is_virtual(self):
+        return self.parent.is_virtual()
+
+    def getitem_raw(self, offset, itemsize, descr):
+        return self.parent.getitem_raw(self.offset+offset, itemsize, descr)        
+
+    def setitem_raw(self, offset, itemsize, descr, itemop):
+        self.parent.setitem_raw(self.offset+offset, itemsize, descr, itemop)
+    
+    def _force_elements(self, op, optforce, descr):
+        xxx
 
 class ArrayPtrInfo(AbstractVirtualPtrInfo):
     _attrs_ = ('length', '_items', 'lenbound', '_clear')
@@ -242,7 +319,7 @@
         visitor.register_virtual_fields(instbox, itemops)
         for i in range(self.getlength()):
             itemop = self._items[i]
-            if (itemop is not None and itemop.type == 'r' and
+            if (itemop is not None and
                 not isinstance(itemop, Const)):
                 ptrinfo = optimizer.getptrinfo(itemop)
                 if ptrinfo and ptrinfo.is_virtual():
@@ -298,7 +375,7 @@
         for index in range(self.getlength()):
             for flddescr in fielddescrs:
                 itemop = self._items[i]
-                if (itemop is not None and itemop.type == 'r' and
+                if (itemop is not None and
                     not isinstance(itemop, Const)):
                     ptrinfo = optimizer.getptrinfo(itemop)
                     if ptrinfo and ptrinfo.is_virtual():
diff --git a/rpython/jit/metainterp/optimizeopt/intbounds.py b/rpython/jit/metainterp/optimizeopt/intbounds.py
--- a/rpython/jit/metainterp/optimizeopt/intbounds.py
+++ b/rpython/jit/metainterp/optimizeopt/intbounds.py
@@ -117,6 +117,8 @@
 
     def optimize_INT_ADD(self, op):
         self.emit_operation(op)
+        if self.is_raw_ptr(op.getarg(0)) or self.is_raw_ptr(op.getarg(1)):
+            return
         b1 = self.getintbound(op.getarg(0))
         b2 = self.getintbound(op.getarg(1))
         r = self.getintbound(op)
@@ -536,6 +538,8 @@
         self._propagate_int_is_true_or_zero(op, 0, 1)
 
     def propagate_bounds_INT_ADD(self, op):
+        if self.is_raw_ptr(op.getarg(0)) or self.is_raw_ptr(op.getarg(1)):
+            return
         b1 = self.getintbound(op.getarg(0))
         b2 = self.getintbound(op.getarg(1))
         r = self.getintbound(op)
diff --git a/rpython/jit/metainterp/optimizeopt/optimizer.py b/rpython/jit/metainterp/optimizeopt/optimizer.py
--- a/rpython/jit/metainterp/optimizeopt/optimizer.py
+++ b/rpython/jit/metainterp/optimizeopt/optimizer.py
@@ -316,6 +316,10 @@
         return opinfo
 
     def getptrinfo(self, op, create=False, is_object=False):
+        if op.type == 'i':
+            return self.getrawptrinfo(op, create)
+        elif op.type == 'f':
+            return None
         assert op.type == 'r'
         op = self.get_box_replacement(op)
         assert op.type == 'r'
@@ -327,6 +331,12 @@
             return fw
         return None
 
+    def is_raw_ptr(self, op):
+        fw = self.get_box_replacement(op).get_forwarded()
+        if isinstance(fw, info.AbstractRawPtrInfo):
+            return True
+        return False
+    
     def getrawptrinfo(self, op, create=False, is_object=False):
         assert op.type == 'i'
         op = self.get_box_replacement(op)
@@ -334,11 +344,14 @@
         if isinstance(op, ConstInt):
             return info.ConstPtrInfo(op)
         fw = op.get_forwarded()
+        if isinstance(fw, IntBound) and not create:
+            return None
         if fw is not None:
-            if isinstance(fw, info.NonNullPtrInfo):
-                fw = info.RawStructPtrInfo()
-                op.set_forwarded(fw)
-            assert isinstance(fw, info.RawStructPtrInfo)
+            if isinstance(fw, info.AbstractRawPtrInfo):
+                return fw
+            fw = info.RawStructPtrInfo()
+            op.set_forwarded(fw)
+            assert isinstance(fw, info.AbstractRawPtrInfo)
             return fw
         return None
 
diff --git a/rpython/jit/metainterp/optimizeopt/rewrite.py b/rpython/jit/metainterp/optimizeopt/rewrite.py
--- a/rpython/jit/metainterp/optimizeopt/rewrite.py
+++ b/rpython/jit/metainterp/optimizeopt/rewrite.py
@@ -121,6 +121,9 @@
             self.optimizer.pure_reverse(op)
 
     def optimize_INT_ADD(self, op):
+        if self.is_raw_ptr(op.getarg(0)) or self.is_raw_ptr(op.getarg(1)):
+            self.emit_operation(op)
+            return
         arg1 = self.get_box_replacement(op.getarg(0))
         b1 = self.getintbound(arg1)
         arg2 = self.get_box_replacement(op.getarg(1))
diff --git a/rpython/jit/metainterp/optimizeopt/virtualize.py b/rpython/jit/metainterp/optimizeopt/virtualize.py
--- a/rpython/jit/metainterp/optimizeopt/virtualize.py
+++ b/rpython/jit/metainterp/optimizeopt/virtualize.py
@@ -543,17 +543,14 @@
         return opinfo
 
     def make_virtual_raw_memory(self, size, source_op):
-        raise Exception("unsupported")
-        logops = self.optimizer.loop.logops
-        vvalue = VRawBufferValue(self.optimizer.cpu, logops, size, source_op)
-        self.make_equal_to(source_op, vvalue)
-        return vvalue
+        opinfo = info.RawBufferPtrInfo(self.optimizer.cpu, size)
+        source_op.set_forwarded(opinfo)
+        return opinfo
 
-    def make_virtual_raw_slice(self, rawbuffer_value, offset, source_op):
-        raise Exception("unsupported")
-        vvalue = VRawSliceValue(rawbuffer_value, offset, source_op)
-        self.make_equal_to(source_op, vvalue)
-        return vvalue
+    def make_virtual_raw_slice(self, offset, parent, source_op):
+        opinfo = info.RawSlicePtrInfo(offset, parent)
+        source_op.set_forwarded(opinfo)
+        return opinfo
 
     def optimize_GUARD_NO_EXCEPTION(self, op):
         if self.last_emitted_operation is REMOVED:
@@ -761,23 +758,20 @@
         self.emit_operation(op)
 
     def optimize_INT_ADD(self, op):
-        if 0:
-            XXX
-            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()
-                # the following check is constant-folded to False if the
-                # translation occurs without any VRawXxxValue instance around
-                if value.is_about_raw:
-                    if isinstance(value, VRawBufferValue):
-                        self.make_virtual_raw_slice(value, offset, op)
-                        return
-                    elif isinstance(value, VRawSliceValue):
-                        offset = offset + value.offset
-                        self.make_virtual_raw_slice(value.rawbuffer_value, offset,
-                                                    op)
-                        return
+        opinfo = self.getrawptrinfo(op.getarg(0), create=False)
+        offsetbox = self.get_constant_box(op.getarg(1))
+        if opinfo and opinfo.is_virtual() and offsetbox is not None:
+            offset = offsetbox.getint()
+            # the following check is constant-folded to False if the
+            # translation occurs without any VRawXxxValue instance around
+            if isinstance(opinfo, info.RawBufferPtrInfo):
+                self.make_virtual_raw_slice(offset, opinfo, op)
+                return
+            elif isinstance(value, VRawSliceValue):
+                offset = offset + value.offset
+                self.make_virtual_raw_slice(value.rawbuffer_value, offset,
+                                            op)
+                return
         self.emit_operation(op)
 
     def optimize_ARRAYLEN_GC(self, op):
@@ -832,13 +826,12 @@
     def optimize_GETARRAYITEM_RAW_I(self, op):
         opinfo = self.getrawptrinfo(op.getarg(0))
         if opinfo and opinfo.is_virtual():
-            raise Exception("implement raw virtuals")
-            xxx
             indexbox = self.get_constant_box(op.getarg(1))
             if indexbox is not None:
-                offset, itemsize, descr = self._unpack_arrayitem_raw_op(op, indexbox)
+                offset, itemsize, descr = self._unpack_arrayitem_raw_op(op,
+                                                                indexbox)
                 try:
-                    itemvalue = value.getitem_raw(offset, itemsize, descr)
+                    itemvalue = opinfo.getitem_raw(offset, itemsize, descr)
                 except InvalidRawOperation:
                     pass
                 else:
@@ -853,11 +846,10 @@
         if opinfo and opinfo.is_virtual():
             indexbox = self.get_constant_box(op.getarg(1))
             if indexbox is not None:
-                raise Exception("implement raw virtuals")
                 offset, itemsize, descr = self._unpack_arrayitem_raw_op(op, indexbox)
-                itemvalue = self.getvalue(op.getarg(2))
+                itemop = self.get_box_replacement(op.getarg(2))
                 try:
-                    value.setitem_raw(offset, itemsize, descr, itemvalue)
+                    opinfo.setitem_raw(offset, itemsize, descr, itemop)
                     return
                 except InvalidRawOperation:
                     pass
diff --git a/rpython/jit/metainterp/pyjitpl.py b/rpython/jit/metainterp/pyjitpl.py
--- a/rpython/jit/metainterp/pyjitpl.py
+++ b/rpython/jit/metainterp/pyjitpl.py
@@ -1573,7 +1573,10 @@
                         return resbox
                 self.metainterp.vable_and_vrefs_before_residual_call()
                 tp = descr.get_result_type()
-                if tp == 'i':
+                if effectinfo.oopspecindex == effectinfo.OS_LIBFFI_CALL:
+                    resbox = self.metainterp.direct_libffi_call(allboxes, descr,
+                                                                tp)
+                elif tp == 'i':
                     resbox = self.metainterp.execute_and_record_varargs(
                         rop.CALL_MAY_FORCE_I, allboxes, descr=descr)
                 elif tp == 'r':
@@ -1601,11 +1604,6 @@
                 if vablebox is not None:
                     self.metainterp.history.record(rop.KEEPALIVE, [vablebox], None)
                 self.metainterp.handle_possible_exception()
-                # XXX refactor: direct_libffi_call() is a hack
-                # does not work in the new system
-                if effectinfo.oopspecindex == effectinfo.OS_LIBFFI_CALL:
-                    raise Exception("implement OS_LIBFFI_CALL properly")
-                #    self.metainterp.direct_libffi_call()
                 return resbox
             else:
                 effect = effectinfo.extraeffect
@@ -2963,9 +2961,8 @@
         else:
             return None, op
 
-    def direct_libffi_call(self):
-        """Generate a direct call to C code, patching the CALL_MAY_FORCE
-        to jit_ffi_call() that occurred just now.
+    def direct_libffi_call(self, argboxes, descr, tp):
+        """Generate a direct call to C code using jit_ffi_call()
         """
         # an 'assert' that constant-folds away the rest of this function
         # if the codewriter didn't produce any OS_LIBFFI_CALL at all.
@@ -2975,33 +2972,19 @@
         from rpython.rlib.jit_libffi import CIF_DESCRIPTION_P
         from rpython.jit.backend.llsupport.ffisupport import get_arg_descr
         #
-        num_extra_guards = 0
-        while True:
-            op = self.history.operations[-1-num_extra_guards]
-            if op.is_call_may_force():
-                break
-            assert op.is_guard()
-            num_extra_guards += 1
-        #
-        box_cif_description = op.getarg(1)
+        box_cif_description = argboxes[1]
         if not isinstance(box_cif_description, ConstInt):
             return
         cif_description = box_cif_description.getint()
         cif_description = llmemory.cast_int_to_adr(cif_description)
         cif_description = llmemory.cast_adr_to_ptr(cif_description,
                                                    CIF_DESCRIPTION_P)
-        extrainfo = op.getdescr().get_extra_info()
+        extrainfo = descr.get_extra_info()
         calldescr = self.cpu.calldescrof_dynamic(cif_description, extrainfo)
         if calldescr is None:
             return
         #
-        extra_guards = []
-        for i in range(num_extra_guards):
-            extra_guards.append(self.history.operations.pop())
-        extra_guards.reverse()
-        #
-        box_exchange_buffer = op.getarg(3)
-        self.history.operations.pop()
+        box_exchange_buffer = argboxes[3]
         arg_boxes = []
 
         for i in range(cif_description.nargs):
@@ -3010,12 +2993,14 @@
             ofs = cif_description.exchange_args[i]
             assert ofs % itemsize == 0     # alignment check
             if kind == 'i':
-                box_arg = self.history.record(rop.GETARRAYITEM_RAW_I,
+                box_arg = self.history.record(
+                    rop.GETARRAYITEM_RAW_I,
                                     [box_exchange_buffer,
                                      ConstInt(ofs // itemsize)],
                                      0, descr)
             elif kind == 'f':
-                box_arg = self.history.record(rop.GETARRAYITEM_RAW_F,
+                box_arg = self.history.record(
+                    rop.GETARRAYITEM_RAW_F,
                                     [box_exchange_buffer,
                                      ConstInt(ofs // itemsize)],
                                      0.0, descr)
@@ -3028,15 +3013,22 @@
         # (that is, errno and SetLastError/GetLastError on Windows)
         # Note these flags match the ones in clibffi.ll_callback
         c_saveall = ConstInt(rffi.RFFI_ERR_ALL | rffi.RFFI_ALT_ERRNO)
-        if op.type == 'i':
-            self.history.record(rop.CALL_RELEASE_GIL,
-                                [c_saveall, op.getarg(2)] + arg_boxes,
-                                box_result, calldescr)
-        #
-        self.history.operations.extend(extra_guards)
+        if tp == 'i':
+            value = executor.execute_varargs(self.cpu, self,
+                                             rop.CALL_MAY_FORCE_I,
+                                             argboxes, descr)
+            box_result = self.history.record(
+                rop.CALL_RELEASE_GIL_I, [c_saveall, argboxes[2]] + arg_boxes,
+                value, descr=calldescr)
+        elif tp == 'f':
+            xxx
+            box_result = self.history.record(
+                rop.CALL_RELEASE_GIL_F, [c_saveall, argboxes[2]] + arg_boxes,
+                value, descr=calldescr)
         #
         # note that the result is written back to the exchange_buffer by the
         # special op libffi_save_result_{int,float}
+        return box_result
 
     def direct_call_release_gil(self):
         op = self.history.operations.pop()
diff --git a/rpython/jit/metainterp/resume.py b/rpython/jit/metainterp/resume.py
--- a/rpython/jit/metainterp/resume.py
+++ b/rpython/jit/metainterp/resume.py
@@ -220,11 +220,13 @@
             elif box in liveboxes:
                 tagged = liveboxes[box]
             else:
+                is_virtual = False
                 if box.type == 'r':
                     info = optimizer.getptrinfo(box)
-                    is_virtual = (info is not None and info.is_virtual())
-                else:
-                    is_virtual = False
+                    is_virtual = (info and info.is_virtual())
+                if box.type == 'i':
+                    info = optimizer.getrawptrinfo(box, create=False)
+                    is_virtual = (info and info.is_virtual()) 
                 if is_virtual:
                     tagged = tag(v, TAGVIRTUAL)
                     v += 1
@@ -390,7 +392,11 @@
                 liveboxes[i] = box
             else:
                 assert tagbits == TAGVIRTUAL
-                info = optimizer.getptrinfo(box)
+                if box.type == 'r':
+                    info = optimizer.getptrinfo(box)
+                else:
+                    assert box.type == 'i'
+                    info = optimizer.getrawptrinfo(box)
                 info.visitor_walk_recursive(box, self, optimizer)
 
         for setfield_op in pending_setfields:
diff --git a/rpython/jit/metainterp/test/test_executor.py b/rpython/jit/metainterp/test/test_executor.py
--- a/rpython/jit/metainterp/test/test_executor.py
+++ b/rpython/jit/metainterp/test/test_executor.py
@@ -97,38 +97,38 @@
     # cases with a descr
     # arity == -1
     argboxes = [InputArgInt(321), ConstInt(123)]
-    box = _execute_nonspec(cpu, FakeMetaInterp(), rop.CALL_F,
+    box = _execute_arglist(cpu, FakeMetaInterp(), rop.CALL_F,
                            argboxes, FakeCallDescr())
     assert box == 42.5
     # arity == 0
-    box = _execute_nonspec(cpu, None, rop.NEW, [], descr)
+    box = _execute_arglist(cpu, None, rop.NEW, [], descr)
     assert box.fakeargs == ('new', descr)
     # arity == 1
     box1 = InputArgRef()
-    box = _execute_nonspec(cpu, None, rop.ARRAYLEN_GC, [box1], descr)
+    box = _execute_arglist(cpu, None, rop.ARRAYLEN_GC, [box1], descr)
     assert box == 55
     # arity == 2
     box2 = boxfloat(222.2)
     fielddescr = FakeFieldDescr()
-    _execute_nonspec(cpu, None, rop.SETFIELD_GC, [box1, box2], fielddescr)
+    _execute_arglist(cpu, None, rop.SETFIELD_GC, [box1, box2], fielddescr)
     assert cpu.fakesetfield == (box1.getref_base(), box2.getfloat(),
                                 fielddescr)
     # arity == 3
     box3 = InputArgInt(33)
     arraydescr = FakeArrayDescr()
-    _execute_nonspec(cpu, None, rop.SETARRAYITEM_GC, [box1, box3, box2],
+    _execute_arglist(cpu, None, rop.SETARRAYITEM_GC, [box1, box3, box2],
                     arraydescr)
     assert cpu.fakesetarrayitem == (box1.getref_base(), box3.getint(),
                                     box2.getfloat(), arraydescr)
     # cases without descr
     # arity == 1
-    box = _execute_nonspec(cpu, None, rop.INT_INVERT, [box3])
+    box = _execute_arglist(cpu, None, rop.INT_INVERT, [box3])
     assert box == ~33
     # arity == 2
-    box = _execute_nonspec(cpu, None, rop.INT_LSHIFT, [box3, InputArgInt(3)])
+    box = _execute_arglist(cpu, None, rop.INT_LSHIFT, [box3, InputArgInt(3)])
     assert box == 33 << 3
     # arity == 3
-    _execute_nonspec(cpu, None, rop.STRSETITEM, [box1, InputArgInt(3), box3])
+    _execute_arglist(cpu, None, rop.STRSETITEM, [box1, InputArgInt(3), box3])
     assert cpu.fakestrsetitem == (box1.getref_base(), 3, box3.getint())
 
 # ints
@@ -245,7 +245,7 @@
 def test_int_ops():
     cpu = FakeCPU()
     for opnum, boxargs, retvalue in get_int_tests():
-        r = _execute_nonspec(cpu, None, opnum, boxargs)
+        r = _execute_arglist(cpu, None, opnum, boxargs)
         assert r == retvalue
 
 # floats
@@ -315,7 +315,7 @@
 def test_float_ops():
     cpu = FakeCPU()
     for opnum, boxargs, rettype, retvalue in get_float_tests(cpu):
-        res = _execute_nonspec(cpu, None, opnum, boxargs)
+        res = _execute_arglist(cpu, None, opnum, boxargs)
         assert res == retvalue
 
 def make_args_for_op(op, a, b):


More information about the pypy-commit mailing list