[pypy-svn] r70313 - in pypy/branch/jit-delayed-write/pypy/jit/metainterp: . test

arigo at codespeak.net arigo at codespeak.net
Mon Dec 28 21:27:06 CET 2009


Author: arigo
Date: Mon Dec 28 21:27:04 2009
New Revision: 70313

Modified:
   pypy/branch/jit-delayed-write/pypy/jit/metainterp/optimizeopt.py
   pypy/branch/jit-delayed-write/pypy/jit/metainterp/resume.py
   pypy/branch/jit-delayed-write/pypy/jit/metainterp/test/test_optimizeopt.py
   pypy/branch/jit-delayed-write/pypy/jit/metainterp/test/test_resume.py
Log:
Fix and mostly finish it.  The previous attempt was a dead-end; instead
just pass a list of pending setfields to the ResumeDataVirtualAdder
which gets stored to 'rd_pendingfields'.  To do later maybe: make the
rd_pendingfields list even more compact.


Modified: pypy/branch/jit-delayed-write/pypy/jit/metainterp/optimizeopt.py
==============================================================================
--- pypy/branch/jit-delayed-write/pypy/jit/metainterp/optimizeopt.py	(original)
+++ pypy/branch/jit-delayed-write/pypy/jit/metainterp/optimizeopt.py	Mon Dec 28 21:27:04 2009
@@ -66,8 +66,7 @@
     def get_backstore(self):
         return (None, None)
 
-    def make_virtual_info(self, modifier, fieldnums,
-                          backstore_num, backstore_descr):
+    def make_virtual_info(self, modifier, fieldnums):
         raise NotImplementedError # should not be called on this level
 
     def is_constant(self):
@@ -142,12 +141,10 @@
 
 
 class AbstractVirtualValue(OptValue):
-    _attrs_ = ('optimizer', 'keybox', 'source_op', '_cached_vinfo',
-               'backstore_field')
+    _attrs_ = ('optimizer', 'keybox', 'source_op', '_cached_vinfo')
     box = None
     level = LEVEL_NONNULL
     _cached_vinfo = None
-    backstore_field = None     # the fielddescr from lazy_setfields
 
     def __init__(self, optimizer, keybox, source_op=None):
         self.optimizer = optimizer
@@ -166,28 +163,12 @@
             self._really_force()
         return self.box
 
-    def get_backstore(self):
-        if self.backstore_field is None:
-            return (None, None)
-        heapopt = self.optimizer.heap_op_optimizer
-        try:
-            op = heapopt.lazy_setfields[self.backstore_field]
-        except KeyError:
-            self.backstore_field = None
-            return (None, None)
-        if self.optimizer.getvalue(op.args[1]) is not self:
-            self.backstore_field = None
-            return (None, None)
-        return (op.args[0], self.backstore_field)
-
-    def make_virtual_info(self, modifier, fieldnums,
-                          backstore_num, backstore_descr):
+    def make_virtual_info(self, modifier, fieldnums):
         vinfo = self._cached_vinfo
-        if vinfo is not None and vinfo.equals(fieldnums, backstore_num,
-                                              backstore_descr):
+        if vinfo is not None and vinfo.equals(fieldnums):
             return vinfo
         vinfo = self._make_virtual(modifier)
-        vinfo.set_content(fieldnums, backstore_num, backstore_descr)
+        vinfo.set_content(fieldnums)
         self._cached_vinfo = vinfo
         return vinfo
 
@@ -562,11 +543,11 @@
         self.newoperations.append(op)
 
     def store_final_boxes_in_guard(self, op):
-        self.heap_op_optimizer.force_lazy_setfields_for_guard()
+        pendingfields = self.heap_op_optimizer.force_lazy_setfields_for_guard()
         descr = op.descr
         assert isinstance(descr, compile.ResumeGuardDescr)
         modifier = resume.ResumeDataVirtualAdder(descr, self.resumedata_memo)
-        newboxes = modifier.finish(self.values)
+        newboxes = modifier.finish(self.values, pendingfields)
         if len(newboxes) > self.metainterp_sd.options.failargs_limit: # XXX be careful here
             raise compile.GiveUp
         descr.store_final_boxes(op, newboxes)
@@ -984,22 +965,18 @@
         except KeyError:
             return
         del self.lazy_setfields[descr]
-        fieldvalue = self.optimizer.getvalue(op.args[1])
-        if isinstance(fieldvalue, AbstractVirtualValue):
-            fieldvalue.backstore_field = None
         self.optimizer._emit_operation(op)
         #
         # hackish: reverse the order of the last two operations if it makes
-        # sense to avoid the situation "int_eq/setfield_gc/guard_true"
+        # sense to avoid a situation like "int_eq/setfield_gc/guard_true",
+        # which the backend (at least the x86 backend) does not handle well.
         newoperations = self.optimizer.newoperations
         if before_guard and len(newoperations) >= 2:
             lastop = newoperations[-1]
             prevop = newoperations[-2]
             if prevop.is_always_pure() and prevop.result not in lastop.args:
-                del newoperations[-1]
-                del newoperations[-1]
-                newoperations.append(lastop)
-                newoperations.append(prevop)
+                newoperations[-2] = lastop
+                newoperations[-1] = prevop
 
     def force_all_lazy_setfields(self):
         if len(self.lazy_setfields_descrs) > 0:
@@ -1008,6 +985,7 @@
             del self.lazy_setfields_descrs[:]
 
     def force_lazy_setfields_for_guard(self):
+        pendingfields = []
         for descr in self.lazy_setfields_descrs:
             try:
                 op = self.lazy_setfields[descr]
@@ -1015,18 +993,17 @@
                 continue
             # the only really interesting case that we need to handle in the
             # guards' resume data is that of a virtual object that is stored
-            # into a field of a non-virtual object.  The later object cannot
-            # actually be virtual here (verified by an assert), but the
-            # former object 'fieldvalue' can be.
+            # into a field of a non-virtual object.
             value = self.optimizer.getvalue(op.args[0])
-            assert not value.is_virtual()
+            assert not value.is_virtual()      # it must be a non-virtual
             fieldvalue = self.optimizer.getvalue(op.args[1])
             if fieldvalue.is_virtual():
-                assert isinstance(fieldvalue, AbstractVirtualValue)
-                if fieldvalue.backstore_field is descr:
-                    # this is the case that can be handled by resume data
-                    continue
-            self.force_lazy_setfield(descr, before_guard=True)
+                # this is the case that we leave to resume.py
+                pendingfields.append((descr, value.box,
+                                      fieldvalue.get_key_box()))
+            else:
+                self.force_lazy_setfield(descr, before_guard=True)
+        return pendingfields
 
     def force_lazy_setfield_if_necessary(self, op, value, write=False):
         try:
@@ -1056,8 +1033,6 @@
     def optimize_SETFIELD_GC(self, op, value, fieldvalue):
         self.force_lazy_setfield_if_necessary(op, value, write=True)
         self.lazy_setfields[op.descr] = op
-        if isinstance(fieldvalue, AbstractVirtualValue):
-            fieldvalue.backstore_field = op.descr
         # remember the result of future reads of the field
         self.cache_field_value(op.descr, value, fieldvalue, write=True)
 

Modified: pypy/branch/jit-delayed-write/pypy/jit/metainterp/resume.py
==============================================================================
--- pypy/branch/jit-delayed-write/pypy/jit/metainterp/resume.py	(original)
+++ pypy/branch/jit-delayed-write/pypy/jit/metainterp/resume.py	Mon Dec 28 21:27:04 2009
@@ -266,7 +266,7 @@
         _, tagbits = untag(tagged)
         return tagbits == TAGVIRTUAL
 
-    def finish(self, values):
+    def finish(self, values, pending_setfields=[]):
         # compute the numbering
         storage = self.storage
         numb, liveboxes_from_env, v = self.memo.number(values,
@@ -289,7 +289,14 @@
                 value = values[box]
                 value.get_args_for_fail(self)
 
+        for _, box, fieldbox in pending_setfields:
+            self.register_box(box)
+            self.register_box(fieldbox)
+            value = values[fieldbox]
+            value.get_args_for_fail(self)
+
         self._number_virtuals(liveboxes, values, v)
+        self._add_pending_fields(pending_setfields)
 
         storage.rd_consts = self.memo.consts
         dump_storage(storage, liveboxes)
@@ -338,13 +345,7 @@
                 value = values[virtualbox]
                 fieldnums = [self._gettagged(box)
                              for box in fieldboxes]
-                backstore_box, backstore_descr = value.get_backstore()
-                if backstore_descr is not None:
-                    backstore_num = self._gettagged(backstore_box)
-                else:
-                    backstore_num = NULLREF
-                vinfo = value.make_virtual_info(self, fieldnums,
-                                                backstore_num, backstore_descr)
+                vinfo = value.make_virtual_info(self, fieldnums)
                 # if a new vinfo instance is made, we get the fieldnums list we
                 # pass in as an attribute. hackish.
                 if vinfo.fieldnums is not fieldnums:
@@ -363,6 +364,16 @@
                 return True
         return False
 
+    def _add_pending_fields(self, pending_setfields):
+        rd_pendingfields = None
+        if pending_setfields:
+            rd_pendingfields = []
+            for descr, box, fieldbox in pending_setfields:
+                num = self._gettagged(box)
+                fieldnum = self._gettagged(fieldbox)
+                rd_pendingfields.append((descr, num, fieldnum))
+        self.storage.rd_pendingfields = rd_pendingfields
+
     def _gettagged(self, box):
         if isinstance(box, Const):
             return self.memo.getconst(box)
@@ -372,46 +383,15 @@
             return self.liveboxes[box]
 
 
-class BackstoreRef(object):
-    # Used to say that a virtual object must, after being created because
-    # of a guard failure, be stored back on the given field of the given
-    # non-virtual object.  For lazy setfields.  Limited to one place per
-    # virtual for now.
-    def __init__(self, parentdescr, parentnum):
-        self.parentdescr = parentdescr
-        self.parentnum = parentnum
-
-    def setfields(self, metainterp, box, fn_decode_box):
-        parentbox = fn_decode_box(self.parentnum)
-        metainterp.execute_and_record(rop.SETFIELD_GC, self.parentdescr,
-                                      parentbox, box)
-
 class AbstractVirtualInfo(object):
-    backstore_ref = None
-
     def allocate(self, metainterp):
         raise NotImplementedError
-
     def setfields(self, metainterp, box, fn_decode_box):
-        if self.backstore_ref is not None:
-            self.backstore_ref.setfields(metainterp, box, fn_decode_box)
-
-    def equals(self, fieldnums, backstore_num, backstore_descr):
-        return (tagged_list_eq(self.fieldnums, fieldnums) and
-                self.backstore_equals(backstore_num, backstore_descr))
-
-    def backstore_equals(self, backstore_num, backstore_descr):
-        if backstore_descr is None:
-            return self.backstore_ref is None
-        else:
-            return (self.backstore_ref is not None and
-                    self.backstore_ref.parentdescr == backstore_descr and
-                    self.backstore_ref.parentnum == backstore_num)
-
-    def set_content(self, fieldnums, backstore_num, backstore_descr):
+        raise NotImplementedError
+    def equals(self, fieldnums):
+        return tagged_list_eq(self.fieldnums, fieldnums)
+    def set_content(self, fieldnums):
         self.fieldnums = fieldnums
-        if backstore_descr is not None:
-            self.backstore_ref = BackstoreRef(backstore_descr, backstore_num)
 
 
 class AbstractVirtualStructInfo(AbstractVirtualInfo):
@@ -425,7 +405,6 @@
             metainterp.execute_and_record(rop.SETFIELD_GC,
                                           self.fielddescrs[i],
                                           box, fieldbox)
-        AbstractVirtualInfo.setfields(self, metainterp, box, fn_decode_box)
 
     def debug_prints(self):
         assert len(self.fielddescrs) == len(self.fieldnums)
@@ -476,7 +455,6 @@
             metainterp.execute_and_record(rop.SETARRAYITEM_GC,
                                           self.arraydescr,
                                           box, ConstInt(i), itembox)
-        AbstractVirtualInfo.setfields(self, metainterp, box, fn_decode_box)
 
     def debug_prints(self):
         debug_print("\tvarrayinfo", self.arraydescr)
@@ -514,6 +492,7 @@
         self.liveboxes = liveboxes
         self.cpu = metainterp.cpu
         self._prepare_virtuals(metainterp, storage.rd_virtuals)
+        self._prepare_pendingfields(metainterp, storage.rd_pendingfields)
 
     def _prepare_virtuals(self, metainterp, virtuals):
         if virtuals:
@@ -532,6 +511,16 @@
                     vinfo.setfields(metainterp, self.virtuals[i],
                                     self._decode_box)
 
+    def _prepare_pendingfields(self, metainterp, pendingfields):
+        if pendingfields:
+            if metainterp._already_allocated_resume_virtuals is not None:
+                return
+            for descr, num, fieldnum in pendingfields:
+                box = self._decode_box(num)
+                fieldbox = self._decode_box(fieldnum)
+                metainterp.execute_and_record(rop.SETFIELD_GC,
+                                              descr, box, fieldbox)
+
     def consume_boxes(self):
         numb = self.cur_numb
         assert numb is not None

Modified: pypy/branch/jit-delayed-write/pypy/jit/metainterp/test/test_optimizeopt.py
==============================================================================
--- pypy/branch/jit-delayed-write/pypy/jit/metainterp/test/test_optimizeopt.py	(original)
+++ pypy/branch/jit-delayed-write/pypy/jit/metainterp/test/test_optimizeopt.py	Mon Dec 28 21:27:04 2009
@@ -87,39 +87,21 @@
 
 def test_reuse_vinfo():
     class FakeVInfo(object):
-        def set_content(self, fieldnums, backstore_num, backstore_descr):
+        def set_content(self, fieldnums):
             self.fieldnums = fieldnums
-            self.backstore_num = backstore_num
-            self.backstore_descr = backstore_descr
-        def equals(self, fieldnums, backstore_num, backstore_descr):
-            return (self.fieldnums == fieldnums and
-                    self.backstore_num == backstore_num and
-                    self.backstore_descr == backstore_descr)
+        def equals(self, fieldnums):
+            return self.fieldnums == fieldnums
     class FakeVirtualValue(optimizeopt.AbstractVirtualValue):
         def _make_virtual(self, *args):
             return FakeVInfo()
     v1 = FakeVirtualValue(None, None, None)
-    vinfo1 = v1.make_virtual_info(None, [1, 2, 4], None, None)
-    vinfo2 = v1.make_virtual_info(None, [1, 2, 4], None, None)
+    vinfo1 = v1.make_virtual_info(None, [1, 2, 4])
+    vinfo2 = v1.make_virtual_info(None, [1, 2, 4])
     assert vinfo1 is vinfo2
-    vinfo3 = v1.make_virtual_info(None, [1, 2, 6], None, None)
+    vinfo3 = v1.make_virtual_info(None, [1, 2, 6])
     assert vinfo3 is not vinfo2
-    vinfo4 = v1.make_virtual_info(None, [1, 2, 6], None, None)
+    vinfo4 = v1.make_virtual_info(None, [1, 2, 6])
     assert vinfo3 is vinfo4
-    #
-    descr = object()
-    descr2 = object()
-    vinfo1 = v1.make_virtual_info(None, [1, 2, 4], None, None)
-    vinfo2 = v1.make_virtual_info(None, [1, 2, 4], 6, descr)
-    assert vinfo1 is not vinfo2
-    vinfo3 = v1.make_virtual_info(None, [1, 2, 4], 6, descr)
-    assert vinfo3 is vinfo2
-    vinfo4 = v1.make_virtual_info(None, [1, 2, 4], 5, descr)
-    assert vinfo4 is not vinfo3
-    vinfo5 = v1.make_virtual_info(None, [1, 2, 4], 5, descr2)
-    assert vinfo5 is not vinfo4
-    vinfo6 = v1.make_virtual_info(None, [1, 2, 4], 5, descr2)
-    assert vinfo6 is vinfo5
 
 def test_descrlist_dict():
     from pypy.jit.metainterp import optimizeutil
@@ -1422,7 +1404,7 @@
         """
         expected = """
         [p1, i2, i3]
-        guard_true(i3) []
+        guard_true(i3) [p1]
         i4 = int_neg(i2)
         setfield_gc(p1, NULL, descr=nextdescr)
         jump(p1, i2, i4)
@@ -1430,6 +1412,26 @@
         self.optimize_loop(ops, 'Not, Not, Not', expected)
 
     def test_duplicate_setfield_residual_guard_3(self):
+        ops = """
+        [p1, i2, i3]
+        p2 = new_with_vtable(ConstClass(node_vtable))
+        setfield_gc(p2, i2, descr=valuedescr)
+        setfield_gc(p1, p2, descr=nextdescr)
+        guard_true(i3) []
+        i4 = int_neg(i2)
+        setfield_gc(p1, NULL, descr=nextdescr)
+        jump(p1, i2, i4)
+        """
+        expected = """
+        [p1, i2, i3]
+        guard_true(i3) [p1, i2]
+        i4 = int_neg(i2)
+        setfield_gc(p1, NULL, descr=nextdescr)
+        jump(p1, i2, i4)
+        """
+        self.optimize_loop(ops, 'Not, Not, Not', expected)
+
+    def test_duplicate_setfield_residual_guard_4(self):
         # test that the setfield_gc does not end up between int_eq and
         # the following guard_true
         ops = """
@@ -1811,6 +1813,14 @@
                 tag = ('virtual', self.namespace[match.group(2)])
             virtuals[pvar] = (tag, None, fieldstext)
         #
+        r2 = re.compile(r"([\w\d()]+)[.](\w+)\s*=\s*([\w\d()]+)")
+        pendingfields = []
+        for match in r2.finditer(text):
+            pvar = match.group(1)
+            pfieldname = match.group(2)
+            pfieldvar = match.group(3)
+            pendingfields.append((pvar, pfieldname, pfieldvar))
+        #
         def _variables_equal(box, varname, strict):
             if varname not in virtuals:
                 if strict:
@@ -1832,11 +1842,21 @@
                 else:
                     virtuals[varname] = tag, box, fieldstext
         #
-        basetext = text[:ends[0]]
+        basetext = text.splitlines()[0]
         varnames = [s.strip() for s in basetext.split(',')]
+        if varnames == ['']:
+            varnames = []
         assert len(boxes) == len(varnames)
         for box, varname in zip(boxes, varnames):
             _variables_equal(box, varname, strict=True)
+        for pvar, pfieldname, pfieldvar in pendingfields:
+            box = oparse.getvar(pvar)
+            fielddescr = self.namespace[pfieldname.strip()]
+            fieldbox = executor.execute(self.cpu,
+                                        rop.GETFIELD_GC,
+                                        fielddescr,
+                                        box)
+            _variables_equal(fieldbox, pfieldvar, strict=True)
         #
         for match in parts:
             pvar = match.group(1)
@@ -2109,14 +2129,16 @@
         """
         expected = """
         [p1, i2, i3]
-        guard_true(i3, descr=fdescr) [i2]
+        guard_true(i3, descr=fdescr) [p1, i2]
         i4 = int_neg(i2)
         setfield_gc(p1, NULL, descr=nextdescr)
         jump(p1, i2, i4)
         """
         self.optimize_loop(ops, 'Not, Not, Not', expected)
+        self.loop.inputargs[0].value = self.nodebox.value
         self.check_expanded_fail_descr('''
-            where p2 is a node_vtable, valuedescr=i2 --> p1.nextdescr
+            p1.nextdescr = p2
+            where p2 is a node_vtable, valuedescr=i2
             ''')
 
     def test_expand_fail_lazy_setfield_2(self):
@@ -2140,7 +2162,8 @@
         """
         self.optimize_loop(ops, 'Not, Not', expected)
         self.check_expanded_fail_descr('''
-            where p2 is a node_vtable, valuedescr=i2 --> myptr.nextdescr
+            ConstPtr(myptr).nextdescr = p2
+            where p2 is a node_vtable, valuedescr=i2
             ''')
 
 

Modified: pypy/branch/jit-delayed-write/pypy/jit/metainterp/test/test_resume.py
==============================================================================
--- pypy/branch/jit-delayed-write/pypy/jit/metainterp/test/test_resume.py	(original)
+++ pypy/branch/jit-delayed-write/pypy/jit/metainterp/test/test_resume.py	Mon Dec 28 21:27:04 2009
@@ -12,6 +12,8 @@
     rd_frame_info_list = None
     rd_numb = None
     rd_consts = []
+    rd_virtuals = None
+    rd_pendingfields = None
 
 def test_tag():
     assert tag(3, 1) == rffi.r_short(3<<2|1)
@@ -42,21 +44,9 @@
 
 def test_vinfo():
     v1 = AbstractVirtualInfo()
-    v1.set_content([1, 2, 4], -1, None)
-    assert v1.backstore_ref is None
-    assert v1.equals([1, 2, 4], -1, None)
-    assert not v1.equals([1, 2, 6], -1, None)
-    assert not v1.equals([1, 2, 4], 3, object())
-    #
-    v2 = AbstractVirtualInfo()
-    descr = object()
-    v2.set_content([1, 2, 4], 3, descr)
-    assert v2.backstore_ref is not None
-    assert v2.backstore_ref.parentdescr is descr
-    assert v2.backstore_ref.parentnum == 3
-    assert v2.equals([1, 2, 4], 3, descr)
-    assert not v2.equals([1, 2, 4], 2, descr)
-    assert not v2.equals([1, 2, 4], 3, object())
+    v1.set_content([1, 2, 4])
+    assert v1.equals([1, 2, 4])
+    assert not v1.equals([1, 2, 6])
 
 class MyMetaInterp:
     _already_allocated_resume_virtuals = None
@@ -98,7 +88,6 @@
                             tag(0, TAGBOX),
                             tag(1, TAGBOX)])
     storage.rd_numb = numb
-    storage.rd_virtuals = None
 
     b1s, b2s, b3s = [BoxInt(), BoxPtr(), BoxInt()]
     assert b1s != b3s
@@ -121,7 +110,6 @@
                             tag(0, TAGBOX),
                             tag(1, TAGBOX)])
     storage.rd_numb = numb
-    storage.rd_virtuals = None
     b1s, b2s, b3s = [BoxInt(), BoxPtr(), BoxInt()]
     assert b1s != b3s
     reader = ResumeDataReader(storage, [b1s, b2s, b3s], MyMetaInterp())
@@ -143,6 +131,7 @@
         rd_virtuals = [FakeVinfo(), None]
         rd_numb = []
         rd_consts = []
+        rd_pendingfields = None
     class FakeMetainterp(object):
         _already_allocated_resume_virtuals = None
         cpu = None
@@ -979,9 +968,8 @@
     assert ptr.b == lltype.nullptr(LLtypeMixin.NODE)
 
 
-def test_virtual_adder_make_virtual_backstore():
-    b2s, b4s, b5s = [BoxPtr(), BoxPtr(), BoxPtr()]
-    c1s = ConstInt(111)
+def test_virtual_adder_pending_fields():
+    b2s, b4s = [BoxPtr(), BoxPtr()]
     storage = Storage()
     memo = ResumeDataLoopMemo(FakeMetaInterpStaticData())
     modifier = ResumeDataVirtualAdder(storage, memo)
@@ -989,60 +977,34 @@
     modifier.liveboxes = {}
     modifier.vfieldboxes = {}
 
-    class FakeOptimizer(object):
-        class cpu:
-            pass
-        def getvalue(self, box):
-            return {b2s: v2, b4s: v4}[box]
-    fakeoptimizer = FakeOptimizer()
-    class HeapOpOptimizer(object):
-        pass
-    fakeoptimizer.heap_op_optimizer = HeapOpOptimizer()
-    class FakeSetFieldOperation(object):
-        args = [b2s, b4s]
-    fakeoptimizer.heap_op_optimizer.lazy_setfields = {
-        LLtypeMixin.nextdescr: FakeSetFieldOperation()}
-
-    v4 = VirtualValue(fakeoptimizer, ConstAddr(LLtypeMixin.node_vtable_adr2,
-                                                LLtypeMixin.cpu), b4s)
-    v4.backstore_field = LLtypeMixin.nextdescr
-    v4.setfield(LLtypeMixin.valuedescr, OptValue(c1s))
-    v4.setfield(LLtypeMixin.otherdescr, OptValue(b5s))
-    v4._cached_sorted_fields = [LLtypeMixin.valuedescr, LLtypeMixin.otherdescr]
-
     v2 = OptValue(b2s)
+    v4 = OptValue(b4s)
+    modifier.register_box(b2s)
+    modifier.register_box(b4s)
 
-    v4.register_virtual_fields(modifier, [c1s, b5s])
+    values = {b4s: v4, b2s: v2}
     liveboxes = []
-    modifier._number_virtuals(liveboxes, {b4s: v4}, 0)
-    assert liveboxes == [b2s, b5s]
+    modifier._number_virtuals(liveboxes, values, 0)
+    assert liveboxes == [b2s, b4s]
+    modifier._add_pending_fields([(LLtypeMixin.nextdescr, b2s, b4s)])
     storage.rd_consts = memo.consts[:]
     storage.rd_numb = None
     # resume
     demo55.next = lltype.nullptr(LLtypeMixin.NODE)
     b2t = BoxPtr(demo55o)
-    b5t = BoxPtr(demo66o)
-    newboxes = _resume_remap(liveboxes, [b2s, b5s], b2t, b5t)
+    b4t = BoxPtr(demo66o)
+    newboxes = _resume_remap(liveboxes, [b2s, b4s], b2t, b4t)
 
     metainterp = MyMetaInterp()
     reader = ResumeDataReader(storage, newboxes, metainterp)
-    assert len(reader.virtuals) == 1
-    b4t = reader._decode_box(modifier._gettagged(b4s))
+    assert reader.virtuals is None
     trace = metainterp.trace
-    b4new = (rop.NEW_WITH_VTABLE, [ConstAddr(LLtypeMixin.node_vtable_adr2,
-                                         LLtypeMixin.cpu)],
-                              b4t, None)
-    b4set1 = (rop.SETFIELD_GC, [b4t, c1s], None, LLtypeMixin.valuedescr)
-    b4set2 = (rop.SETFIELD_GC, [b4t, b5t], None, LLtypeMixin.otherdescr)
     b2set = (rop.SETFIELD_GC, [b2t, b4t], None, LLtypeMixin.nextdescr)
-    expected = [b4new, b4set1, b4set2, b2set]
+    expected = [b2set]
 
     for x, y in zip(expected, trace):
         assert x == y
-    ptr = demo55.next
-    assert ptr.value == 111
-    ptr = lltype.cast_pointer(lltype.Ptr(LLtypeMixin.NODE2), ptr)
-    assert ptr.other == demo66
+    assert demo55.next == demo66
 
 
 def test_invalidation_needed():



More information about the Pypy-commit mailing list