[pypy-commit] pypy optresult: enough virtual array of structs support

fijal noreply at buildbot.pypy.org
Sun Mar 8 09:47:41 CET 2015


Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: optresult
Changeset: r76278:9508bc587256
Date: 2015-03-08 10:47 +0200
http://bitbucket.org/pypy/pypy/changeset/9508bc587256/

Log:	enough virtual array of structs support

diff --git a/rpython/jit/backend/llgraph/runner.py b/rpython/jit/backend/llgraph/runner.py
--- a/rpython/jit/backend/llgraph/runner.py
+++ b/rpython/jit/backend/llgraph/runner.py
@@ -151,7 +151,7 @@
             rffi.cast(TYPE, -1) == -1)
 
 class ArrayDescr(AbstractDescr):
-    def __init__(self, A):
+    def __init__(self, A, runner):
         self.A = self.OUTERA = A
         if isinstance(A, lltype.Struct):
             self.A = A._flds[A._arrayfld]
@@ -191,10 +191,12 @@
 
 
 class InteriorFieldDescr(AbstractDescr):
-    def __init__(self, A, fieldname):
+    def __init__(self, A, fieldname, runner):
         self.A = A
         self.fieldname = fieldname
         self.FIELD = getattr(A.OF, fieldname)
+        self.arraydescr = runner.arraydescrof(A)
+        self.fielddescr = runner.fielddescrof(A.OF, fieldname)
 
     def __repr__(self):
         return 'InteriorFieldDescr(%r, %r)' % (self.A, self.fieldname)
@@ -397,8 +399,12 @@
         try:
             return self.descrs[key]
         except KeyError:
-            descr = ArrayDescr(A)
+            descr = ArrayDescr(A, self)
             self.descrs[key] = descr
+            if isinstance(A.OF, lltype.Struct):
+                descrs = heaptracker.all_interiorfielddescrs(self,
+                        A, get_field_descr=LLGraphCPU.interiorfielddescrof)
+                descr.all_interiorfielddescrs = descrs
             return descr
 
     def interiorfielddescrof(self, A, fieldname):
@@ -406,7 +412,7 @@
         try:
             return self.descrs[key]
         except KeyError:
-            descr = InteriorFieldDescr(A, fieldname)
+            descr = InteriorFieldDescr(A, fieldname, self)
             self.descrs[key] = descr
             return descr
 
diff --git a/rpython/jit/codewriter/heaptracker.py b/rpython/jit/codewriter/heaptracker.py
--- a/rpython/jit/codewriter/heaptracker.py
+++ b/rpython/jit/codewriter/heaptracker.py
@@ -157,6 +157,25 @@
             res.append(get_field_descr(gccache, STRUCT, name))
     return res
 
+def all_interiorfielddescrs(gccache, ARRAY, get_field_descr=None):
+    from rpython.jit.backend.llsupport import descr
+
+    if get_field_descr is None:
+        get_field_descr = descr.get_field_descr
+    # order is not relevant, except for tests
+    STRUCT = ARRAY.OF
+    res = []
+    for name in STRUCT._names:
+        FIELD = getattr(STRUCT, name)
+        if FIELD is lltype.Void:
+            continue
+        if name == 'typeptr':
+            continue # dealt otherwise
+        elif isinstance(FIELD, lltype.Struct):
+            raise Exception("unexpected array(struct(struct))")
+        res.append(get_field_descr(gccache, ARRAY, name))
+    return res
+
 def gc_fielddescrs(gccache, STRUCT):
     return all_fielddescrs(gccache, STRUCT, True)
 
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
@@ -53,9 +53,8 @@
     def is_nonnull(self):
         return True
 
-
-class AbstractStructPtrInfo(NonNullPtrInfo):
-    _attrs_ = ('_is_virtual', '_fields')
+class AbstractVirtualPtrInfo(NonNullPtrInfo):
+    _attrs_ = ('_is_virtual',)
 
     def force_box(self, op, optforce):
         if self._is_virtual:
@@ -65,18 +64,16 @@
             op.set_forwarded(newop)
             newop.set_forwarded(self)
             self._is_virtual = False
-            if self._fields is not None:
-                descr = op.getdescr()
-                for i, flddescr in enumerate(descr.all_fielddescrs):
-                    fld = self._fields[i]
-                    if fld is not None:
-                        subbox = optforce.force_box(fld)
-                        setfieldop = ResOperation(rop.SETFIELD_GC, [op, subbox],
-                                                  descr=flddescr)
-                        optforce.emit_operation(setfieldop)
+            self._force_elements(newop, optforce)
             return newop
         return op
 
+    def is_virtual(self):
+        return self._is_virtual
+
+class AbstractStructPtrInfo(AbstractVirtualPtrInfo):
+    _attrs_ = ('_is_virtual', '_fields')
+
     def init_fields(self, descr):
         self._fields = [None] * len(descr.all_fielddescrs)
 
@@ -86,8 +83,17 @@
     def getfield_virtual(self, descr):
         return self._fields[descr.index]
 
-    def is_virtual(self):
-        return self._is_virtual
+    def _force_elements(self, op, optforce):
+        if self._fields is None:
+            return
+        descr = op.getdescr()
+        for i, flddescr in enumerate(descr.all_fielddescrs):
+            fld = self._fields[i]
+            if fld is not None:
+                subbox = optforce.force_box(fld)
+                setfieldop = ResOperation(rop.SETFIELD_GC, [op, subbox],
+                                          descr=flddescr)
+                optforce.emit_operation(setfieldop)
 
 class InstancePtrInfo(AbstractStructPtrInfo):
     _attrs_ = ('_known_class')
@@ -100,13 +106,44 @@
     def get_known_class(self, cpu):
         return self._known_class
     
-class StructPtrInfo(NonNullPtrInfo):
-    _attrs_ = ('is_virtual', '_fields')
+class StructPtrInfo(AbstractStructPtrInfo):
+    pass
+    
+class ArrayPtrInfo(AbstractVirtualPtrInfo):
+    _attrs_ = ('_is_virtual', 'length', '_items', '_descr')
 
-    
-class ArrayPtrInfo(NonNullPtrInfo):
-    _attrs_ = ('is_virtual', 'length', '_items')
+class ArrayStructInfo(ArrayPtrInfo):
+    def __init__(self, descr, size, is_virtual):
+        self.length = size
+        lgt = len(descr.all_interiorfielddescrs)
+        self._is_virtual = is_virtual
+        self._items = [None] * (size * lgt)
 
+    def _compute_index(self, index, fielddescr):
+        one_size = len(fielddescr.arraydescr.all_interiorfielddescrs)
+        return index * one_size + fielddescr.fielddescr.index
+        
+    def setinteriorfield_virtual(self, index, fielddescr, fld):
+        index = self._compute_index(index, fielddescr)
+        self._items[index] = fld
+
+    def getinteriorfield_virtual(self, index, fielddescr):
+        index = self._compute_index(index, fielddescr)
+        return self._items[index]
+
+    def _force_elements(self, op, optforce):
+        i = 0
+        fielddescrs = op.getdescr().all_interiorfielddescrs
+        for index in range(self.length):
+            for flddescr in fielddescrs:
+                fld = self._items[i]
+                if fld is not None:
+                    subbox = optforce.force_box(fld)
+                    setfieldop = ResOperation(rop.SETINTERIORFIELD_GC,
+                                              [op, subbox],
+                                              descr=flddescr)
+                    optforce.emit_operation(setfieldop)
+                i += 1
     
 class StrPtrInfo(NonNullPtrInfo):
     _attrs_ = ()
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
@@ -205,10 +205,11 @@
         # Constant fold f0 * 1.0 and turn f0 * -1.0 into a FLOAT_NEG, these
         # work in all cases, including NaN and inf
         for lhs, rhs in [(arg1, arg2), (arg2, arg1)]:
-            v1 = self.getvalue(lhs)
-            v2 = self.getvalue(rhs)
+            v1 = self.get_box_replacement(lhs)
+            v2 = self.get_box_replacement(rhs)
 
             if v1.is_constant():
+                xxxx
                 if v1.box.getfloatstorage() == 1.0:
                     self.make_equal_to(op, v2)
                     return
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
@@ -531,6 +531,9 @@
     def make_varray(self, arraydescr, size, source_op, clear=False):
         if arraydescr.is_array_of_structs():
             assert clear
+            opinfo = info.ArrayStructInfo(arraydescr, size, True)
+            source_op.set_forwarded(opinfo)
+            return opinfo
             vvalue = VArrayStructValue(arraydescr, size, source_op)
         else:
             constvalue = self.new_const_item(arraydescr)
@@ -697,7 +700,8 @@
     def optimize_SETFIELD_GC(self, op):
         opinfo = self.getptrinfo(op.getarg(0))
         if opinfo is not None and opinfo.is_virtual():
-            opinfo.setfield_virtual(op.getdescr(), op.getarg(1))
+            opinfo.setfield_virtual(op.getdescr(),
+                                    self.get_box_replacement(op.getarg(1)))
         else:
             self.make_nonnull(op.getarg(0))
             self.emit_operation(op)
@@ -718,8 +722,7 @@
     def optimize_NEW_ARRAY_CLEAR(self, op):
         sizebox = self.get_constant_box(op.getarg(0))
         if sizebox is not None:
-            self.make_varray(op.getdescr(), sizebox.getint(), op,
-                             clear=True)
+            self.make_varray(op.getdescr(), sizebox.getint(), op, clear=True)
         else:
             self.emit_operation(op)        
 
@@ -893,32 +896,33 @@
         self.emit_operation(op)
 
     def optimize_GETINTERIORFIELD_GC_I(self, op):
-        value = self.getvalue(op.getarg(0))
-        if value.is_virtual():
+        opinfo = self.getptrinfo(op.getarg(0))
+        if opinfo and opinfo.is_virtual():
             indexbox = self.get_constant_box(op.getarg(1))
             if indexbox is not None:
                 descr = op.getdescr()
-                fieldvalue = value.getinteriorfield(
-                    indexbox.getint(), descr, None
-                )
-                if fieldvalue is None:
+                fld = opinfo.getinteriorfield_virtual(indexbox.getint(), descr)
+                if fld is None:
+                    xxx
                     fieldvalue = self.new_const(descr)
-                self.make_equal_to(op, fieldvalue)
+                self.make_equal_to(op, fld)
                 return
+        xxx
         value.ensure_nonnull()
         self.emit_operation(op)
     optimize_GETINTERIORFIELD_GC_R = optimize_GETINTERIORFIELD_GC_I
     optimize_GETINTERIORFIELD_GC_F = optimize_GETINTERIORFIELD_GC_I
 
     def optimize_SETINTERIORFIELD_GC(self, op):
-        value = self.getvalue(op.getarg(0))
-        if value.is_virtual():
+        opinfo = self.getptrinfo(op.getarg(0))
+        if opinfo and opinfo.is_virtual():
             indexbox = self.get_constant_box(op.getarg(1))
             if indexbox is not None:
-                value.setinteriorfield(
-                    indexbox.getint(), op.getdescr(), self.getvalue(op.getarg(2))
-                )
+                opinfo.setinteriorfield_virtual(indexbox.getint(),
+                                                op.getdescr(),
+                                       self.get_box_replacement(op.getarg(2)))
                 return
+        xxx
         value.ensure_nonnull()
         self.emit_operation(op)
 


More information about the pypy-commit mailing list