Author: Maciej Fijalkowski <[email protected]>
Branch: optresult
Changeset: r76328:9b36048a749a
Date: 2015-03-11 17:05 +0200
http://bitbucket.org/pypy/pypy/changeset/9b36048a749a/

Log:    make the fisrt heapcache test pass

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
@@ -89,11 +89,15 @@
         return getkind(self.RESULT)[0]
 
 class SizeDescr(AbstractDescr):
-    def __init__(self, S, runner):
+    def __init__(self, S, is_object, runner):
         self.S = S
+        self._is_object = is_object
         self.all_fielddescrs = heaptracker.all_fielddescrs(runner, S,
                                     get_field_descr=LLGraphCPU.fielddescrof)
 
+    def is_object(self):
+        return self._is_object
+
     def as_vtable_size_descr(self):
         return self
 
@@ -374,12 +378,12 @@
             self.descrs[key] = descr
             return descr
 
-    def sizeof(self, S):
+    def sizeof(self, S, is_object):
         key = ('size', S)
         try:
             return self.descrs[key]
         except KeyError:
-            descr = SizeDescr(S, self)
+            descr = SizeDescr(S, is_object, self)
             self.descrs[key] = descr
             return descr
 
@@ -390,6 +394,8 @@
         except KeyError:
             descr = FieldDescr(S, fieldname)
             self.descrs[key] = descr
+            is_obj = heaptracker.has_gcstruct_a_vtable(S)
+            descr.parent_descr = self.sizeof(S, is_obj)
             if self.vinfo_for_tests is not None:
                 descr.vinfo = self.vinfo_for_tests
             return descr
diff --git a/rpython/jit/backend/llsupport/descr.py 
b/rpython/jit/backend/llsupport/descr.py
--- a/rpython/jit/backend/llsupport/descr.py
+++ b/rpython/jit/backend/llsupport/descr.py
@@ -48,10 +48,16 @@
     def repr_of_descr(self):
         return '<SizeDescr %s>' % self.size
 
+    def is_object(self):
+        return False
+
 class SizeDescrWithVTable(SizeDescr):
     def as_vtable_size_descr(self):
         return self
 
+    def is_object(self):
+        return True
+
 BaseSizeDescr = SizeDescr
 
 def get_size_descr(gccache, STRUCT):
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
@@ -87,7 +87,7 @@
 
 def register_known_gctype(cpu, vtable, STRUCT):
     # register the correspondance 'vtable' <-> 'STRUCT' in the cpu
-    sizedescr = cpu.sizeof(STRUCT)
+    sizedescr = cpu.sizeof(STRUCT, has_gcstruct_a_vtable(STRUCT))
     assert sizedescr.as_vtable_size_descr() is sizedescr
     try:
         assert sizedescr._corresponding_vtable == vtable
diff --git a/rpython/jit/metainterp/optimizeopt/earlyforce.py 
b/rpython/jit/metainterp/optimizeopt/earlyforce.py
--- a/rpython/jit/metainterp/optimizeopt/earlyforce.py
+++ b/rpython/jit/metainterp/optimizeopt/earlyforce.py
@@ -1,3 +1,4 @@
+
 from rpython.jit.codewriter.effectinfo import EffectInfo
 from rpython.jit.metainterp.optimizeopt.optimizer import Optimization
 from rpython.jit.metainterp.resoperation import rop
@@ -14,8 +15,7 @@
     def propagate_forward(self, op):
         opnum = op.getopnum()
 
-        if 0:   # XXX
-          if (opnum != rop.SETFIELD_GC and
+        if (opnum != rop.SETFIELD_GC and
             opnum != rop.SETARRAYITEM_GC and
             opnum != rop.SETARRAYITEM_RAW and
             opnum != rop.QUASIIMMUT_FIELD and
@@ -26,9 +26,7 @@
             not is_raw_free(op, opnum)):
 
             for arg in op.getarglist():
-                if arg in self.optimizer.values:
-                    value = self.getvalue(arg)
-                    value.force_box(self)
+                self.optimizer.force_box(arg)
         self.emit_operation(op)
 
     def setup(self):
diff --git a/rpython/jit/metainterp/optimizeopt/heap.py 
b/rpython/jit/metainterp/optimizeopt/heap.py
--- a/rpython/jit/metainterp/optimizeopt/heap.py
+++ b/rpython/jit/metainterp/optimizeopt/heap.py
@@ -5,8 +5,7 @@
 from rpython.jit.metainterp.history import Const, ConstInt
 from rpython.jit.metainterp.jitexc import JitException
 from rpython.jit.metainterp.optimizeopt.optimizer import Optimization, REMOVED
-from rpython.jit.metainterp.optimizeopt.info import MODE_ARRAY,\
-     LEVEL_KNOWNCLASS
+from rpython.jit.metainterp.optimizeopt.info import MODE_ARRAY
 from rpython.jit.metainterp.optimizeopt.util import make_dispatcher_method
 from rpython.jit.metainterp.optimizeopt.intutils import IntBound
 from rpython.jit.metainterp.optimize import InvalidLoop
@@ -30,6 +29,7 @@
         #      value pending in the ResOperation is *not* visible in
         #      'cached_fields'.
         #
+        Xxxx
         self._cached_fields = {}
         self._cached_fields_getfield_op = {}
         self._lazy_setfield = None
@@ -186,8 +186,8 @@
     """Cache repeated heap accesses"""
 
     def __init__(self):
-        # cached fields:  {descr: CachedField}
-        self.cached_fields = {}
+        # mapping descr -> infos to invalidate
+        self.infos_to_invalidate = {}
         # cached array items:  {array descr: {index: CachedField}}
         self.cached_arrayitems = {}
         # cached dict items: {dict descr: {(optval, index): box-or-const}}
@@ -203,15 +203,6 @@
     def setup(self):
         self.optimizer.optheap = self
 
-    def value_updated(self, oldvalue, newvalue):
-        # XXXX very unhappy about that
-        for cf in self.cached_fields.itervalues():
-            cf.value_updated(oldvalue, newvalue, 
self.optimizer.exporting_state)
-        for submap in self.cached_arrayitems.itervalues():
-            for cf in submap.itervalues():
-                cf.value_updated(oldvalue, newvalue,
-                                 self.optimizer.exporting_state)
-
     def force_at_end_of_preamble(self):
         self.cached_dict_reads.clear()
         self.corresponding_array_descrs.clear()
@@ -247,9 +238,22 @@
             for index, d in submap.items():
                 d.produce_potential_short_preamble_ops(self.optimizer, sb, 
descr)
 
+    def invalidate_descr(self, descr, lst=None):
+        if lst is not None:
+            lst = self.infos_to_invalidate.get(descr, None)
+            if lst is None:
+                return
+        for info in lst:
+            info.clear_cache()
+        del lst[:]
+
+    def register_dirty_field(self, descr, info):
+        self.infos_to_invalidate.setdefault(descr, []).append(info)
+
     def clean_caches(self):
         del self._lazy_setfields_and_arrayitems[:]
-        self.cached_fields.clear()
+        for descr, info in self.infos_to_invalidate.iteritems():
+            self.invalidate_descr(descr, info)
         self.cached_arrayitems.clear()
         self.cached_dict_reads.clear()
 
@@ -478,7 +482,15 @@
         return pendingfields
 
     def optimize_GETFIELD_GC_I(self, op):
+        opinfo = self.ensure_ptr_info_arg0(op)
+        fld = opinfo.getfield(op.getdescr())
+        if fld is not None:
+            self.make_equal_to(op, fld)
+            return
         self.emit_operation(op)
+        opinfo.setfield(op.getdescr(), op, self)
+        return
+        xxx
         return
         structvalue = self.getvalue(op.getarg(0))
         cf = self.field_cache(op.getdescr())
@@ -522,6 +534,8 @@
         cf.do_setfield(self, op)
 
     def optimize_GETARRAYITEM_GC_I(self, op):
+        self.emit_operation(op)
+        return # XXX
         arrayvalue = self.getvalue(op.getarg(0))
         indexvalue = self.getvalue(op.getarg(1))
         cf = None
@@ -569,6 +583,8 @@
     optimize_GETARRAYITEM_GC_PURE_F = optimize_GETARRAYITEM_GC_PURE_I
 
     def optimize_SETARRAYITEM_GC(self, op):
+        self.emit_operation(op)
+        return
         opnum = OpHelpers.getarrayitem_pure_for_descr(op.getdescr())
         if self.has_pure_result(opnum, [op.getarg(0), op.getarg(1)],
                                 op.getdescr()):
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
@@ -8,19 +8,20 @@
 lower two bits are LEVEL
 """
 
-LEVEL_UNKNOWN    = 0
-LEVEL_NONNULL    = 1
-LEVEL_KNOWNCLASS = 2     # might also mean KNOWNARRAYDESCR, for arrays
-LEVEL_CONSTANT   = 3
 
 MODE_ARRAY   = '\x00'
 MODE_STR     = '\x01'
 MODE_UNICODE = '\x02'
+MODE_INSTANCE = '\x03'
+MODE_STRUCT = '\x04'
 
 INFO_NULL = 0
 INFO_NONNULL = 1
 INFO_UNKNOWN = 2
 
+FLAG_VIRTUAL = 1
+FLAG_DIRTY = 2
+
 class AbstractInfo(AbstractValue):
     is_info_class = True
 
@@ -55,39 +56,54 @@
         return True
 
 class AbstractVirtualPtrInfo(NonNullPtrInfo):
-    _attrs_ = ('_is_virtual',)
+    _attrs_ = ('flags',)
+
+    flags = 0
 
     def force_box(self, op, optforce):
-        if self._is_virtual:
+        if self.is_virtual():
             op.set_forwarded(None)
             optforce.emit_operation(op)
             newop = optforce.getlastop()
             op.set_forwarded(newop)
             newop.set_forwarded(self)
-            self._is_virtual = False
-            self._force_elements(newop, optforce)
+            self.flags &= ~FLAG_VIRTUAL # clean the virtual flag
+            if self._force_elements(newop, optforce):
+                self.flags |= FLAG_DIRTY
             return newop
         return op
 
     def is_virtual(self):
-        return self._is_virtual
+        return self.flags & FLAG_VIRTUAL
 
 class AbstractStructPtrInfo(AbstractVirtualPtrInfo):
-    _attrs_ = ('_is_virtual', '_fields')
+    _attrs_ = ('_fields',)
 
     def init_fields(self, descr):
         self._fields = [None] * len(descr.all_fielddescrs)
 
-    def setfield_virtual(self, descr, op):
+    def clear_cache(self):
+        assert self.flags & (FLAG_DIRTY | FLAG_VIRTUAL) == FLAG_DIRTY
+        self.flags = 0
+        self._fields = [None] * len(self._fields)
+
+    def setfield(self, descr, op, optheap=None):
+        if not self.is_virtual():
+            if self.flags & FLAG_DIRTY == 0:
+                self.flags |= FLAG_DIRTY
+                assert optheap is not None
+                # we should only call it with virtuals without optheap
+                optheap.register_dirty_field(descr, self)
         self._fields[descr.index] = op
 
-    def getfield_virtual(self, descr):
+    def getfield(self, descr):
         return self._fields[descr.index]
 
     def _force_elements(self, op, optforce):
         if self._fields is None:
-            return
+            return 0
         descr = op.getdescr()
+        count = 0
         for i, flddescr in enumerate(descr.all_fielddescrs):
             fld = self._fields[i]
             if fld is not None:
@@ -95,6 +111,10 @@
                 setfieldop = ResOperation(rop.SETFIELD_GC, [op, subbox],
                                           descr=flddescr)
                 optforce.emit_operation(setfieldop)
+                if optforce.optheap:
+                    optforce.optheap.register_dirty_field(flddescr, self)
+                count += 1
+        return count
 
 class InstancePtrInfo(AbstractStructPtrInfo):
     _attrs_ = ('_known_class')
@@ -102,25 +122,44 @@
 
     def __init__(self, known_class=None, is_virtual=False):
         self._known_class = known_class
-        self._is_virtual = is_virtual
+        if is_virtual:
+            self.flags = FLAG_VIRTUAL
 
     def get_known_class(self, cpu):
         return self._known_class
     
 class StructPtrInfo(AbstractStructPtrInfo):
-    pass
+    def __init__(self, is_virtual=False):
+        if is_virtual:
+            self.flags = FLAG_VIRTUAL
     
 class ArrayPtrInfo(AbstractVirtualPtrInfo):
-    _attrs_ = ('_is_virtual', 'length', '_items', '_descr')
+    _attrs_ = ('length', '_items', '_descr')
 
     def __init__(self, descr, const, size, clear, is_virtual):
-        self._is_virtual = is_virtual
+        if is_virtual:
+            self.flags = FLAG_VIRTUAL
         self.length = size
         if clear:
             self._items = [const] * size
         else:
             self._items = [None] * size
 
+    def _force_elements(self, op, optforce):
+        arraydescr = op.getdescr()
+        count = 0
+        for i in range(self.length):
+            item = self._items[i]
+            if item is not None:
+                subbox = optforce.force_box(item)
+                setop = ResOperation(rop.SETARRAYITEM_GC,
+                                     [op, ConstInt(i), subbox],
+                                      descr=arraydescr)
+                optforce.emit_operation(setop)
+                # xxxx optforce.optheap
+                count += 1
+        return count
+
     def setitem_virtual(self, index, item):
         self._items[index] = item
 
@@ -134,7 +173,8 @@
     def __init__(self, descr, size, is_virtual):
         self.length = size
         lgt = len(descr.all_interiorfielddescrs)
-        self._is_virtual = is_virtual
+        if is_virtual:
+            self.flags = FLAG_VIRTUAL
         self._items = [None] * (size * lgt)
 
     def _compute_index(self, index, fielddescr):
@@ -152,6 +192,7 @@
     def _force_elements(self, op, optforce):
         i = 0
         fielddescrs = op.getdescr().all_interiorfielddescrs
+        count = 0
         for index in range(self.length):
             for flddescr in fielddescrs:
                 fld = self._items[i]
@@ -161,7 +202,10 @@
                                               [op, ConstInt(index), subbox],
                                               descr=flddescr)
                     optforce.emit_operation(setfieldop)
+                    # XXX optforce.optheap
+                    count += 1
                 i += 1
+        return count
     
 class StrPtrInfo(NonNullPtrInfo):
     _attrs_ = ()
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
@@ -71,21 +71,21 @@
     optimize_GUARD_VALUE = _optimize_guard_true_false_value
 
     def optimize_INT_OR_or_XOR(self, op):
-        v1 = self.getvalue(op.getarg(0))
-        v2 = self.getvalue(op.getarg(1))
-        if v1.box is v2.box:
+        v1 = self.get_box_replacement(op.getarg(0))
+        b1 = self.getintbound(v1)
+        v2 = self.get_box_replacement(op.getarg(1))
+        b2 = self.getintbound(v2)
+        if v1 is v2:
             if op.getopnum() == rop.INT_OR:
                 self.make_equal_to(op, v1)
             else:
                 self.make_constant_int(op, 0)
             return
         self.emit_operation(op)
-        bound1 = v1.getintbound()
-        bound2 = v2.getintbound()
-        if bound1.known_ge(IntBound(0, 0)) and \
-           bound2.known_ge(IntBound(0, 0)):
-            r = self.getvalue(op).getintbound()
-            mostsignificant = bound1.upper | bound2.upper
+        if b1.known_ge(IntBound(0, 0)) and \
+           b2.known_ge(IntBound(0, 0)):
+            r = self.getintbound(op)
+            mostsignificant = b1.upper | b2.upper
             r.intersect(IntBound(0, next_pow2_m1(mostsignificant)))
 
     optimize_INT_OR = optimize_INT_OR_or_XOR
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
@@ -304,7 +304,7 @@
         op.set_forwarded(opinfo)
         return opinfo
 
-    def getptrinfo(self, op):
+    def getptrinfo(self, op, create=False, is_object=False):
         assert op.type == 'r'
         op = self.get_box_replacement(op)
         assert op.type == 'r'
@@ -325,8 +325,8 @@
     def replace_op_with(self, op, newopnum, args=None, descr=None):
         return self.optimizer.replace_op_with(op, newopnum, args, descr)
 
-    def get_box_replacement(self, box):
-        return self.optimizer.get_box_replacement(box)
+    def ensure_ptr_info_arg0(self, op):
+        return self.optimizer.ensure_ptr_info_arg0(op)
 
     def make_constant(self, box, constbox):
         return self.optimizer.make_constant(box, constbox)
@@ -575,6 +575,35 @@
             return
         op.set_forwarded(info.NonNullPtrInfo())
 
+    def ensure_ptr_info_arg0(self, op):
+        arg0 = self.get_box_replacement(op.getarg(0))
+        if arg0.is_constant():
+            return info.ConstPtrInfo(arg0)
+        opinfo = arg0.get_forwarded()
+        if isinstance(opinfo, info.AbstractVirtualPtrInfo):
+            return opinfo
+        assert opinfo is None or opinfo.__class__ is info.NonNullPtrInfo
+        if op.is_getfield() or op.getopnum() == rop.SETFIELD_GC:
+            is_object = op.getdescr().parent_descr.is_object()
+            if is_object:
+                opinfo = info.InstancePtrInfo()
+            else:
+                xxx
+            opinfo.init_fields(op.getdescr().parent_descr)
+        else:
+            yyy
+        arg0.set_forwarded(opinfo)
+        return opinfo
+
+    def make_ptr_info(self, op, mode):
+        op = self.get_box_replacement(op)
+        if op.is_constant():
+            return info.ConstPtrInfo(op)
+        opinfo = op.get_forwarded()
+        if isinstance(opinfo, info.AbstractVirtualPtrInfo):
+            return opinfo
+        xxx
+
     def new_const(self, fieldofs):
         if fieldofs.is_pointer_field():
             return self.cpu.ts.CONST_NULL
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py 
b/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py
@@ -199,14 +199,14 @@
     def test_remove_guard_class_2(self):
         ops = """
         [i0]
-        p0 = new_with_vtable(ConstClass(node_vtable), descr=nodesize)
+        p0 = new_with_vtable(descr=nodesize)
         escape_n(p0)
         guard_class(p0, ConstClass(node_vtable)) []
         jump(i0)
         """
         expected = """
         [i0]
-        p0 = new_with_vtable(ConstClass(node_vtable), descr=nodesize)
+        p0 = new_with_vtable(descr=nodesize)
         escape_n(p0)
         jump(i0)
         """
@@ -426,7 +426,7 @@
     def test_ooisnull_oononnull_via_virtual(self):
         ops = """
         [p0]
-        pv = new_with_vtable(ConstClass(node_vtable), descr=nodesize)
+        pv = new_with_vtable(descr=nodesize)
         setfield_gc(pv, p0, descr=valuedescr)
         guard_nonnull(p0) []
         p1 = getfield_gc_r(pv, descr=valuedescr)
@@ -575,7 +575,7 @@
         [i1, p2, p3]
         i3 = getfield_gc_i(p3, descr=valuedescr)
         escape_n(i3)
-        p1 = new_with_vtable(ConstClass(node_vtable), descr=nodesize)
+        p1 = new_with_vtable(descr=nodesize)
         setfield_gc(p1, i1, descr=valuedescr)
         jump(i1, p1, p2)
         """
@@ -587,9 +587,9 @@
         [i1, p2, p3]
         i3 = getfield_gc_i(p3, descr=valuedescr)
         escape_n(i3)
-        p1 = new_with_vtable(ConstClass(node_vtable), descr=nodesize)
+        p1 = new_with_vtable(descr=nodesize)
         setfield_gc(p1, i1, descr=valuedescr)
-        p1sub = new_with_vtable(ConstClass(node_vtable2), descr=nodesize2)
+        p1sub = new_with_vtable(descr=nodesize2)
         setfield_gc(p1sub, i1, descr=valuedescr)
         setfield_gc(p1, p1sub, descr=nextdescr)
         jump(i1, p1, p2)
@@ -604,10 +604,10 @@
         p3sub = getfield_gc_r(p3, descr=nextdescr)
         i3 = getfield_gc_i(p3sub, descr=valuedescr)
         escape_n(i3)
-        p2sub = new_with_vtable(ConstClass(node_vtable2), descr=nodesize2)
+        p2sub = new_with_vtable(descr=nodesize2)
         setfield_gc(p2sub, i1, descr=valuedescr)
         setfield_gc(p2, p2sub, descr=nextdescr)
-        p1 = new_with_vtable(ConstClass(node_vtable), descr=nodesize)
+        p1 = new_with_vtable(descr=nodesize)
         jump(i1, p1, p2)
         """
         # The same as test_p123_simple, but in the end the "old" p2 contains
@@ -736,6 +736,7 @@
                            expected)
 
     def test_virtual_2(self):
+        py.test.skip("XXX")
         ops = """
         [i, p0]
         i0 = getfield_gc(p0, descr=valuedescr)
@@ -749,7 +750,6 @@
         i1 = int_add(i2, i)
         jump(i, i1)
         """
-        py.test.skip("XXX")
         self.optimize_loop(ops, 'Not, Virtual(node_vtable, valuedescr=Not)',
                            expected)
 
@@ -807,6 +807,7 @@
         self.optimize_loop(ops, expected2)
 
     def test_virtual_default_field(self):
+        py.test.skip("XXX")
         ops = """
         [p0]
         i0 = getfield_gc(p0, descr=valuedescr)
@@ -822,14 +823,13 @@
         """
         # the 'expected' is sub-optimal, but it should be done by another later
         # optimization step.  See test_find_nodes_default_field() for why.
-        py.test.skip("XXX")
         self.optimize_loop(ops, 'Virtual(node_vtable, valuedescr=Not)',
                            expected)
 
     def test_virtual_3(self):
         ops = """
         [i]
-        p1 = new_with_vtable(ConstClass(node_vtable), descr=nodesize)
+        p1 = new_with_vtable(descr=nodesize)
         setfield_gc(p1, i, descr=valuedescr)
         i0 = getfield_gc_i(p1, descr=valuedescr)
         i1 = int_add(i0, 1)
@@ -843,13 +843,14 @@
         self.optimize_loop(ops, expected)
 
     def test_virtual_4(self):
+        py.test.skip("XXX")
         ops = """
         [i0, p0]
         guard_class(p0, ConstClass(node_vtable)) []
         i1 = getfield_gc(p0, descr=valuedescr)
         i2 = int_sub(i1, 1)
         i3 = int_add(i0, i1)
-        p1 = new_with_vtable(ConstClass(node_vtable))
+        p1 = new_with_vtable(descr=nodesize)
         setfield_gc(p1, i2, descr=valuedescr)
         jump(i3, p1)
         """
@@ -859,11 +860,11 @@
         i3 = int_add(i0, i1)
         jump(i3, i2)
         """
-        py.test.skip("XXX")
         self.optimize_loop(ops, 'Not, Virtual(node_vtable, valuedescr=Not)',
                            expected)
 
     def test_virtual_5(self):
+        py.test.skip("XXX")
         ops = """
         [i0, p0]
         guard_class(p0, ConstClass(node_vtable)) []
@@ -883,7 +884,6 @@
         i3 = int_add(i0, i1)
         jump(i3, i2, i1)
         """
-        py.test.skip("XXX")
         self.optimize_loop(ops,
             '''Not, Virtual(node_vtable,
                             valuedescr=Not,
@@ -894,7 +894,7 @@
     def test_virtual_constant_isnull(self):
         ops = """
         [i0]
-        p0 = new_with_vtable(ConstClass(node_vtable), descr=nodesize)
+        p0 = new_with_vtable(descr=nodesize)
         setfield_gc(p0, NULL, descr=nextdescr)
         p2 = getfield_gc_r(p0, descr=nextdescr)
         i1 = ptr_eq(p2, NULL)
@@ -909,7 +909,7 @@
     def test_virtual_constant_isnonnull(self):
         ops = """
         [i0]
-        p0 = new_with_vtable(ConstClass(node_vtable), descr=nodesize)
+        p0 = new_with_vtable(descr=nodesize)
         setfield_gc(p0, ConstPtr(myptr), descr=nextdescr)
         p2 = getfield_gc_r(p0, descr=nextdescr)
         i1 = ptr_eq(p2, NULL)
@@ -1020,7 +1020,7 @@
     def test_nonvirtual_1(self):
         ops = """
         [i]
-        p1 = new_with_vtable(ConstClass(node_vtable), descr=nodesize)
+        p1 = new_with_vtable(descr=nodesize)
         setfield_gc(p1, i, descr=valuedescr)
         i0 = getfield_gc_i(p1, descr=valuedescr)
         i1 = int_add(i0, 1)
@@ -1031,7 +1031,7 @@
         expected = """
         [i]
         i1 = int_add(i, 1)
-        p1 = new_with_vtable(ConstClass(node_vtable), descr=nodesize)
+        p1 = new_with_vtable(descr=nodesize)
         setfield_gc(p1, i, descr=valuedescr)
         escape_n(p1)
         escape_n(p1)
@@ -1045,7 +1045,7 @@
         i0 = getfield_gc_i(p0, descr=valuedescr)
         escape_n(p0)
         i1 = int_add(i0, i)
-        p1 = new_with_vtable(ConstClass(node_vtable), descr=nodesize)
+        p1 = new_with_vtable(descr=nodesize)
         setfield_gc(p1, i1, descr=valuedescr)
         jump(i, p1)
         """
@@ -1055,7 +1055,7 @@
     def test_nonvirtual_later(self):
         ops = """
         [i]
-        p1 = new_with_vtable(ConstClass(node_vtable), descr=nodesize)
+        p1 = new_with_vtable(descr=nodesize)
         setfield_gc(p1, i, descr=valuedescr)
         i1 = getfield_gc_i(p1, descr=valuedescr)
         escape_n(p1)
@@ -1065,7 +1065,7 @@
         """
         expected = """
         [i]
-        p1 = new_with_vtable(ConstClass(node_vtable), descr=nodesize)
+        p1 = new_with_vtable(descr=nodesize)
         setfield_gc(p1, i, descr=valuedescr)
         escape_n(p1)
         i2 = getfield_gc_i(p1, descr=valuedescr)
@@ -1077,7 +1077,7 @@
     def test_nonvirtual_write_null_fields_on_force(self):
         ops = """
         [i]
-        p1 = new_with_vtable(ConstClass(node_vtable), descr=nodesize)
+        p1 = new_with_vtable(descr=nodesize)
         setfield_gc(p1, i, descr=valuedescr)
         i1 = getfield_gc_i(p1, descr=valuedescr)
         setfield_gc(p1, 0, descr=valuedescr)
@@ -1087,7 +1087,7 @@
         """
         expected = """
         [i]
-        p1 = new_with_vtable(ConstClass(node_vtable), descr=nodesize)
+        p1 = new_with_vtable(descr=nodesize)
         setfield_gc(p1, 0, descr=valuedescr)
         escape_n(p1)
         i2 = getfield_gc_i(p1, descr=valuedescr)
@@ -1098,7 +1098,7 @@
     def test_getfield_gc_pure_1(self):
         ops = """
         [i]
-        p1 = new_with_vtable(ConstClass(node_vtable), descr=nodesize)
+        p1 = new_with_vtable(descr=nodesize)
         setfield_gc(p1, i, descr=valuedescr)
         i1 = getfield_gc_pure_i(p1, descr=valuedescr)
         jump(i1)
@@ -1189,8 +1189,8 @@
         """
         expected = """
         [i1, p0]
+        setarrayitem_gc(p0, 0, i1, descr=arraydescr)
         p1 = new_array(i1, descr=arraydescr)
-        setarrayitem_gc(p0, 0, i1, descr=arraydescr)
         jump(i1, p1)
         """
         self.optimize_loop(ops, expected)
@@ -1250,7 +1250,7 @@
     def test_varray_forced_1(self):
         ops = """
         []
-        p2 = new_with_vtable(ConstClass(node_vtable))
+        p2 = new_with_vtable(descr=nodesize)
         setfield_gc(p2, 3, descr=valuedescr)
         i1 = getfield_gc_i(p2, descr=valuedescr)    # i1 = const 3
         p1 = new_array(i1, descr=arraydescr)
@@ -1270,6 +1270,7 @@
         self.optimize_loop(ops, expected)
 
     def test_vstruct_1(self):
+        py.test.skip("XXX")
         ops = """
         [i1, p2]
         i2 = getfield_gc(p2, descr=adescr)
@@ -1283,7 +1284,6 @@
         escape_n(i2)
         jump(i1, i1)
         """
-        py.test.skip("XXX")
         self.optimize_loop(ops, 'Not, VStruct(ssize, adescr=Not)', expected)
 
     def test_p123_vstruct(self):
@@ -1565,6 +1565,7 @@
         self.optimize_loop(ops, expected)
 
     def test_duplicate_setfield_5(self):
+        xxx
         ops = """
         [p0, i1]
         p1 = new_with_vtable(ConstClass(node_vtable))
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_util.py 
b/rpython/jit/metainterp/optimizeopt/test/test_util.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_util.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_util.py
@@ -109,8 +109,8 @@
     myptr2 = lltype.cast_opaque_ptr(llmemory.GCREF, lltype.malloc(NODE))
     nullptr = lltype.nullptr(llmemory.GCREF.TO)
     #nodebox2 = InputArgRef(lltype.cast_opaque_ptr(llmemory.GCREF, node2))
-    nodesize = cpu.sizeof(NODE)
-    nodesize2 = cpu.sizeof(NODE2)
+    nodesize = cpu.sizeof(NODE, True)
+    nodesize2 = cpu.sizeof(NODE2, True)
     valuedescr = cpu.fielddescrof(NODE, 'value')
     floatdescr = cpu.fielddescrof(NODE, 'floatval')
     chardescr = cpu.fielddescrof(NODE, 'charval')
@@ -122,7 +122,7 @@
     QUASI = lltype.GcStruct('QUASIIMMUT', ('inst_field', lltype.Signed),
                             ('mutate_field', rclass.OBJECTPTR),
                             hints={'immutable_fields': accessor})
-    quasisize = cpu.sizeof(QUASI)
+    quasisize = cpu.sizeof(QUASI, False)
     quasi = lltype.malloc(QUASI, immortal=True)
     quasi.inst_field = -4247
     quasifielddescr = cpu.fielddescrof(QUASI, 'inst_field')
@@ -157,7 +157,7 @@
 
     # a GcStruct not inheriting from OBJECT
     S = lltype.GcStruct('TUPLE', ('a', lltype.Signed), ('b', lltype.Ptr(NODE)))
-    ssize = cpu.sizeof(S)
+    ssize = cpu.sizeof(S, False)
     adescr = cpu.fielddescrof(S, 'a')
     bdescr = cpu.fielddescrof(S, 'b')
     #sbox = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, lltype.malloc(S)))
@@ -166,7 +166,7 @@
     T = lltype.GcStruct('TUPLE',
                         ('c', lltype.Signed),
                         ('d', lltype.Ptr(lltype.GcArray(lltype.Ptr(NODE)))))
-    tsize = cpu.sizeof(T)
+    tsize = cpu.sizeof(T, False)
     cdescr = cpu.fielddescrof(T, 'c')
     ddescr = cpu.fielddescrof(T, 'd')
     arraydescr3 = cpu.arraydescrof(lltype.GcArray(lltype.Ptr(NODE)))
@@ -176,7 +176,7 @@
                         ('one', lltype.Ptr(lltype.GcArray(lltype.Ptr(NODE)))))
     u_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True)
     u_vtable_adr = llmemory.cast_ptr_to_adr(u_vtable)
-    usize = cpu.sizeof(U)
+    usize = cpu.sizeof(U, True)
     onedescr = cpu.fielddescrof(U, 'one')
 
     FUNC = lltype.FuncType([lltype.Signed], lltype.Signed)
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
@@ -1,6 +1,6 @@
 from rpython.jit.codewriter.effectinfo import EffectInfo
 from rpython.jit.metainterp.executor import execute
-from rpython.jit.codewriter.heaptracker import vtable2descr
+from rpython.jit.codewriter.heaptracker import vtable2descr, descr2vtable
 from rpython.jit.metainterp.history import Const, ConstInt, BoxInt
 from rpython.jit.metainterp.history import CONST_NULL, BoxPtr
 from rpython.jit.metainterp.optimizeopt import info, optimizer
@@ -15,7 +15,6 @@
 
 class AbstractVirtualInfo(info.PtrInfo):
     _attrs_ = ('_cached_vinfo',)
-    _tag = info.LEVEL_NONNULL
     is_about_raw = False
     _cached_vinfo = None
 
@@ -188,7 +187,6 @@
             fieldvalue.visitor_walk_recursive(visitor)
 
 class VirtualInfo(AbstractVirtualStructInfo):
-    _tag = info.LEVEL_KNOWNCLASS
 
     def __init__(self, known_class, descr):
         AbstractVirtualStructInfo.__init__(self)
@@ -539,9 +537,10 @@
         return opinfo
 
     def make_vstruct(self, structdescr, source_op):
-        vvalue = VStructValue(self.optimizer.cpu, structdescr, source_op)
-        self.make_equal_to(source_op, vvalue)
-        return vvalue
+        opinfo = info.StructPtrInfo(True)
+        opinfo.init_fields(structdescr)
+        source_op.set_forwarded(opinfo)
+        return opinfo
 
     def make_virtual_raw_memory(self, size, source_op):
         logops = self.optimizer.loop.logops
@@ -678,7 +677,7 @@
         #            self.make_equal_to(op, fieldvalue)
         #            return
         if opinfo and opinfo.is_virtual():
-            fieldop = opinfo.getfield_virtual(op.getdescr())
+            fieldop = opinfo.getfield(op.getdescr())
             if fieldop is None:
                 xxx
                 fieldvalue = self.optimizer.new_const(op.getdescr())
@@ -698,14 +697,15 @@
     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(),
-                                    self.get_box_replacement(op.getarg(1)))
+            opinfo.setfield(op.getdescr(),
+                            self.get_box_replacement(op.getarg(1)))
         else:
             self.make_nonnull(op.getarg(0))
             self.emit_operation(op)
 
     def optimize_NEW_WITH_VTABLE(self, op):
-        self.make_virtual(op.getarg(0), op, op.getdescr())
+        known_class = ConstInt(descr2vtable(self.optimizer.cpu, op.getdescr()))
+        self.make_virtual(known_class, op, op.getdescr())
 
     def optimize_NEW(self, op):
         self.make_vstruct(op.getdescr(), op)
diff --git a/rpython/jit/metainterp/optimizeopt/virtualstate.py 
b/rpython/jit/metainterp/optimizeopt/virtualstate.py
--- a/rpython/jit/metainterp/optimizeopt/virtualstate.py
+++ b/rpython/jit/metainterp/optimizeopt/virtualstate.py
@@ -3,8 +3,6 @@
         ConstPtr, ConstFloat)
 from rpython.jit.metainterp.optimizeopt import virtualize
 from rpython.jit.metainterp.optimizeopt.intutils import IntUnbounded
-from rpython.jit.metainterp.optimizeopt.info import (LEVEL_CONSTANT,
-    LEVEL_KNOWNCLASS, LEVEL_NONNULL, LEVEL_UNKNOWN)
 from rpython.jit.metainterp.resoperation import rop, ResOperation,\
      AbstractInputArg
 from rpython.jit.metainterp.compile import Memo
diff --git a/rpython/jit/metainterp/resoperation.py 
b/rpython/jit/metainterp/resoperation.py
--- a/rpython/jit/metainterp/resoperation.py
+++ b/rpython/jit/metainterp/resoperation.py
@@ -223,6 +223,10 @@
     def is_call(self):
         return rop._CALL_FIRST <= self.getopnum() <= rop._CALL_LAST
 
+    def is_getfield(self):
+        return self.opnum in (rop.GETFIELD_GC_I, rop.GETFIELD_GC_F,
+                              rop.GETFIELD_GC_R)
+
     def is_real_call(self):
         opnum = self.opnum
         return (opnum == rop.CALL_I or
@@ -719,7 +723,7 @@
     'GETFIELD_RAW/1d/fi',
     '_MALLOC_FIRST',
     'NEW/0d/r',           #-> GcStruct, gcptrs inside are zeroed (not the rest)
-    'NEW_WITH_VTABLE/1d/r',#-> GcStruct with vtable, gcptrs inside are zeroed
+    'NEW_WITH_VTABLE/0d/r',#-> GcStruct with vtable, gcptrs inside are zeroed
     'NEW_ARRAY/1d/r',     #-> GcArray, not zeroed. only for arrays of 
primitives
     'NEW_ARRAY_CLEAR/1d/r',#-> GcArray, fully zeroed
     'NEWSTR/1/r',         #-> STR, the hash field is zeroed
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to