[pypy-svn] r79068 - in pypy/trunk/pypy/jit/metainterp: . test

arigo at codespeak.net arigo at codespeak.net
Sat Nov 13 19:11:39 CET 2010


Author: arigo
Date: Sat Nov 13 19:11:37 2010
New Revision: 79068

Modified:
   pypy/trunk/pypy/jit/metainterp/compile.py
   pypy/trunk/pypy/jit/metainterp/resume.py
   pypy/trunk/pypy/jit/metainterp/test/test_optimizeopt.py
   pypy/trunk/pypy/jit/metainterp/test/test_resume.py
   pypy/trunk/pypy/jit/metainterp/virtualizable.py
Log:
Rewrite the class Numbering as a ll GcStruct containing an Array part.
This is a bit of a hack, but it's very useful; it can save 10% of memory
in agaynor's example.


Modified: pypy/trunk/pypy/jit/metainterp/compile.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/compile.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/compile.py	Sat Nov 13 19:11:37 2010
@@ -1,4 +1,5 @@
 
+from pypy.rpython.lltypesystem import lltype
 from pypy.rpython.ootypesystem import ootype
 from pypy.objspace.flow.model import Constant, Variable
 from pypy.rlib.objectmodel import we_are_translated
@@ -14,6 +15,7 @@
 from pypy.jit.metainterp.specnode import NotSpecNode, more_general_specnodes
 from pypy.jit.metainterp.typesystem import llhelper, oohelper
 from pypy.jit.metainterp.optimizeutil import InvalidLoop
+from pypy.jit.metainterp.resume import NUMBERING
 from pypy.jit.codewriter import heaptracker
 
 def giveup():
@@ -217,7 +219,7 @@
     # this class also gets the following attributes stored by resume.py code
     rd_snapshot = None
     rd_frame_info_list = None
-    rd_numb = None
+    rd_numb = lltype.nullptr(NUMBERING)
     rd_consts = None
     rd_virtuals = None
     rd_pendingfields = None

Modified: pypy/trunk/pypy/jit/metainterp/resume.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/resume.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/resume.py	Sat Nov 13 19:11:37 2010
@@ -65,12 +65,21 @@
     snapshot = Snapshot(snapshot, boxes)
     storage.rd_snapshot = snapshot
 
-class Numbering(object):
-    __slots__ = ('prev', 'nums')
-
-    def __init__(self, prev, nums):
-        self.prev = prev
-        self.nums = nums
+#
+# The following is equivalent to the RPython-level declaration:
+#
+#     class Numbering: __slots__ = ['prev', 'nums']
+#
+# except that it is more compact in translated programs, because the
+# array 'nums' is inlined in the single NUMBERING object.  This is
+# important because this is often the biggest single consumer of memory
+# in a pypy-c-jit.
+#
+NUMBERINGP = lltype.Ptr(lltype.GcForwardReference())
+NUMBERING = lltype.GcStruct('Numbering',
+                            ('prev', NUMBERINGP),
+                            ('nums', lltype.Array(rffi.SHORT)))
+NUMBERINGP.TO.become(NUMBERING)
 
 TAGMASK = 3
 
@@ -162,7 +171,7 @@
 
     def number(self, values, snapshot):
         if snapshot is None:
-            return None, {}, 0
+            return lltype.nullptr(NUMBERING), {}, 0
         if snapshot in self.numberings:
              numb, liveboxes, v = self.numberings[snapshot]
              return numb, liveboxes.copy(), v
@@ -171,7 +180,7 @@
         n = len(liveboxes)-v
         boxes = snapshot.boxes
         length = len(boxes)
-        nums = [UNASSIGNED] * length
+        numb = lltype.malloc(NUMBERING, length)
         for i in range(length):
             box = boxes[i]
             value = values.get(box, None)
@@ -190,9 +199,9 @@
                     tagged = tag(n, TAGBOX)
                     n += 1
                 liveboxes[box] = tagged
-            nums[i] = tagged
+            numb.nums[i] = tagged
         #
-        numb = Numbering(numb1, nums)
+        numb.prev = numb1
         self.numberings[snapshot] = numb, liveboxes, v
         return numb, liveboxes.copy(), v
 
@@ -297,7 +306,7 @@
         # compute the numbering
         storage = self.storage
         # make sure that nobody attached resume data to this guard yet
-        assert storage.rd_numb is None
+        assert not storage.rd_numb
         numb, liveboxes_from_env, v = self.memo.number(values,
                                                        storage.rd_snapshot)
         self.liveboxes_from_env = liveboxes_from_env
@@ -722,34 +731,36 @@
         self.boxes_f = boxes_f
         self._prepare_next_section(info)
 
-    def consume_virtualizable_boxes(self, vinfo, nums):
+    def consume_virtualizable_boxes(self, vinfo, numb):
         # we have to ignore the initial part of 'nums' (containing vrefs),
         # find the virtualizable from nums[-1], and use it to know how many
         # boxes of which type we have to return.  This does not write
         # anything into the virtualizable.
-        virtualizablebox = self.decode_ref(nums[-1])
+        index = len(numb.nums) - 1
+        virtualizablebox = self.decode_ref(numb.nums[index])
         virtualizable = vinfo.unwrap_virtualizable_box(virtualizablebox)
-        return vinfo.load_list_of_boxes(virtualizable, self, nums)
+        return vinfo.load_list_of_boxes(virtualizable, self, numb)
 
-    def consume_virtualref_boxes(self, nums, end):
+    def consume_virtualref_boxes(self, numb, end):
         # Returns a list of boxes, assumed to be all BoxPtrs.
         # We leave up to the caller to call vrefinfo.continue_tracing().
         assert (end & 1) == 0
-        return [self.decode_ref(nums[i]) for i in range(end)]
+        return [self.decode_ref(numb.nums[i]) for i in range(end)]
 
     def consume_vref_and_vable_boxes(self, vinfo, ginfo):
-        nums = self.cur_numb.nums
-        self.cur_numb = self.cur_numb.prev
+        numb = self.cur_numb
+        self.cur_numb = numb.prev
         if vinfo is not None:
-            virtualizable_boxes = self.consume_virtualizable_boxes(vinfo, nums)
-            end = len(nums) - len(virtualizable_boxes)
+            virtualizable_boxes = self.consume_virtualizable_boxes(vinfo, numb)
+            end = len(numb.nums) - len(virtualizable_boxes)
         elif ginfo is not None:
-            virtualizable_boxes = [self.decode_ref(nums[-1])]
-            end = len(nums) - 1
+            index = len(numb.nums) - 1
+            virtualizable_boxes = [self.decode_ref(numb.nums[index])]
+            end = len(numb.nums) - 1
         else:
             virtualizable_boxes = None
-            end = len(nums)
-        virtualref_boxes = self.consume_virtualref_boxes(nums, end)
+            end = len(numb.nums)
+        virtualref_boxes = self.consume_virtualref_boxes(numb, end)
         return virtualizable_boxes, virtualref_boxes
 
     def allocate_with_vtable(self, known_class):
@@ -977,23 +988,24 @@
         info = blackholeinterp.get_current_position_info()
         self._prepare_next_section(info)
 
-    def consume_virtualref_info(self, vrefinfo, nums, end):
+    def consume_virtualref_info(self, vrefinfo, numb, end):
         # we have to decode a list of references containing pairs
         # [..., virtual, vref, ...]  stopping at 'end'
         assert (end & 1) == 0
         for i in range(0, end, 2):
-            virtual = self.decode_ref(nums[i])
-            vref = self.decode_ref(nums[i+1])
+            virtual = self.decode_ref(numb.nums[i])
+            vref = self.decode_ref(numb.nums[i+1])
             # For each pair, we store the virtual inside the vref.
             vrefinfo.continue_tracing(vref, virtual)
 
-    def consume_vable_info(self, vinfo, nums):
+    def consume_vable_info(self, vinfo, numb):
         # we have to ignore the initial part of 'nums' (containing vrefs),
         # find the virtualizable from nums[-1], load all other values
         # from the CPU stack, and copy them into the virtualizable
         if vinfo is None:
-            return len(nums)
-        virtualizable = self.decode_ref(nums[-1])
+            return len(numb.nums)
+        index = len(numb.nums) - 1
+        virtualizable = self.decode_ref(numb.nums[index])
         virtualizable = vinfo.cast_gcref_to_vtype(virtualizable)
         if self.resume_after_guard_not_forced == 1:
             # in the middle of handle_async_forcing()
@@ -1005,7 +1017,7 @@
             # is and stays 0.  Note the call to reset_vable_token() in
             # warmstate.py.
             assert not virtualizable.vable_token
-        return vinfo.write_from_resume_data_partial(virtualizable, self, nums)
+        return vinfo.write_from_resume_data_partial(virtualizable, self, numb)
 
     def load_value_of_type(self, TYPE, tagged):
         from pypy.jit.metainterp.warmstate import specialize_value
@@ -1022,12 +1034,12 @@
     load_value_of_type._annspecialcase_ = 'specialize:arg(1)'
 
     def consume_vref_and_vable(self, vrefinfo, vinfo, ginfo):
-        nums = self.cur_numb.nums
-        self.cur_numb = self.cur_numb.prev
+        numb = self.cur_numb
+        self.cur_numb = numb.prev
         if self.resume_after_guard_not_forced != 2:
-            end_vref = self.consume_vable_info(vinfo, nums)
+            end_vref = self.consume_vable_info(vinfo, numb)
             if ginfo is not None: end_vref -= 1
-            self.consume_virtualref_info(vrefinfo, nums, end_vref)
+            self.consume_virtualref_info(vrefinfo, numb, end_vref)
 
     def allocate_with_vtable(self, known_class):
         from pypy.jit.metainterp.executor import exec_new_with_vtable
@@ -1180,8 +1192,9 @@
                         'at', compute_unique_id(frameinfo))
             frameinfo = frameinfo.prev
         numb = storage.rd_numb
-        while numb is not None:
-            debug_print('\tnumb', str([untag(i) for i in numb.nums]),
+        while numb:
+            debug_print('\tnumb', str([untag(numb.nums[i])
+                                       for i in range(len(numb.nums))]),
                         'at', compute_unique_id(numb))
             numb = numb.prev
         for const in storage.rd_consts:

Modified: pypy/trunk/pypy/jit/metainterp/test/test_optimizeopt.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/test/test_optimizeopt.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/test/test_optimizeopt.py	Sat Nov 13 19:11:37 2010
@@ -51,12 +51,12 @@
     #
     opt.store_final_boxes_in_guard(op)
     if op.getfailargs() == [b0, b1]:
-        assert fdescr.rd_numb.nums      == [tag(1, TAGBOX)]
-        assert fdescr.rd_numb.prev.nums == [tag(0, TAGBOX)]
+        assert list(fdescr.rd_numb.nums)      == [tag(1, TAGBOX)]
+        assert list(fdescr.rd_numb.prev.nums) == [tag(0, TAGBOX)]
     else:
         assert op.getfailargs() == [b1, b0]
-        assert fdescr.rd_numb.nums      == [tag(0, TAGBOX)]
-        assert fdescr.rd_numb.prev.nums == [tag(1, TAGBOX)]
+        assert list(fdescr.rd_numb.nums)      == [tag(0, TAGBOX)]
+        assert list(fdescr.rd_numb.prev.nums) == [tag(1, TAGBOX)]
     assert fdescr.rd_virtuals is None
     assert fdescr.rd_consts == []
 

Modified: pypy/trunk/pypy/jit/metainterp/test/test_resume.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/test/test_resume.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/test/test_resume.py	Sat Nov 13 19:11:37 2010
@@ -142,6 +142,13 @@
     assert bh.written_f == expected_f
 
 
+def Numbering(prev, nums):
+    numb = lltype.malloc(NUMBERING, len(nums))
+    numb.prev = prev or lltype.nullptr(NUMBERING)
+    for i in range(len(nums)):
+        numb.nums[i] = nums[i]
+    return numb
+
 def test_simple_read():
     #b1, b2, b3 = [BoxInt(), BoxPtr(), BoxInt()]
     c1, c2, c3 = [ConstInt(111), ConstInt(222), ConstInt(333)]
@@ -391,15 +398,15 @@
     assert fi1.pc == 3
 
 def test_Numbering_create():
-    l = [1, 2]
+    l = [rffi.r_short(1), rffi.r_short(2)]
     numb = Numbering(None, l)
-    assert numb.prev is None
-    assert numb.nums is l
+    assert not numb.prev
+    assert list(numb.nums) == l
 
-    l1 = ['b3']
+    l1 = [rffi.r_short(3)]
     numb1 = Numbering(numb, l1)
-    assert numb1.prev is numb
-    assert numb1.nums is l1
+    assert numb1.prev == numb
+    assert list(numb1.nums) == l1
 
 def test_capture_resumedata():
     b1, b2, b3 = [BoxInt(), BoxPtr(), BoxInt()]
@@ -765,11 +772,12 @@
 
     assert liveboxes == {b1: tag(0, TAGBOX), b2: tag(1, TAGBOX),
                          b3: tag(2, TAGBOX)}
-    assert numb.nums == [tag(3, TAGINT), tag(2, TAGBOX), tag(0, TAGBOX),
-                         tag(1, TAGINT)]
-    assert numb.prev.nums == [tag(0, TAGBOX), tag(1, TAGINT), tag(1, TAGBOX),
-                              tag(0, TAGBOX), tag(2, TAGINT)]
-    assert numb.prev.prev is None
+    assert list(numb.nums) == [tag(3, TAGINT), tag(2, TAGBOX), tag(0, TAGBOX),
+                               tag(1, TAGINT)]
+    assert list(numb.prev.nums) == [tag(0, TAGBOX), tag(1, TAGINT),
+                                    tag(1, TAGBOX),
+                                    tag(0, TAGBOX), tag(2, TAGINT)]
+    assert not numb.prev.prev
 
     numb2, liveboxes2, v = memo.number({}, snap2)
     assert v == 0
@@ -777,9 +785,9 @@
     assert liveboxes2 == {b1: tag(0, TAGBOX), b2: tag(1, TAGBOX),
                          b3: tag(2, TAGBOX)}
     assert liveboxes2 is not liveboxes
-    assert numb2.nums == [tag(3, TAGINT), tag(2, TAGBOX), tag(0, TAGBOX),
-                         tag(3, TAGINT)]
-    assert numb2.prev is numb.prev
+    assert list(numb2.nums) == [tag(3, TAGINT), tag(2, TAGBOX), tag(0, TAGBOX),
+                                tag(3, TAGINT)]
+    assert numb2.prev == numb.prev
 
     env3 = [c3, b3, b1, c3]
     snap3 = Snapshot(snap, env3)
@@ -800,9 +808,9 @@
     assert v == 0
     
     assert liveboxes3 == {b1: tag(0, TAGBOX), b2: tag(1, TAGBOX)}
-    assert numb3.nums == [tag(3, TAGINT), tag(4, TAGINT), tag(0, TAGBOX),
-                          tag(3, TAGINT)]
-    assert numb3.prev is numb.prev
+    assert list(numb3.nums) == [tag(3, TAGINT), tag(4, TAGINT), tag(0, TAGBOX),
+                                tag(3, TAGINT)]
+    assert numb3.prev == numb.prev
 
     # virtual
     env4 = [c3, b4, b1, c3]
@@ -813,9 +821,9 @@
     
     assert liveboxes4 == {b1: tag(0, TAGBOX), b2: tag(1, TAGBOX),
                           b4: tag(0, TAGVIRTUAL)}
-    assert numb4.nums == [tag(3, TAGINT), tag(0, TAGVIRTUAL), tag(0, TAGBOX),
-                          tag(3, TAGINT)]
-    assert numb4.prev is numb.prev
+    assert list(numb4.nums) == [tag(3, TAGINT), tag(0, TAGVIRTUAL),
+                                tag(0, TAGBOX), tag(3, TAGINT)]
+    assert numb4.prev == numb.prev
 
     env5 = [b1, b4, b5]
     snap5 = Snapshot(snap4, env5)    
@@ -826,9 +834,9 @@
     
     assert liveboxes5 == {b1: tag(0, TAGBOX), b2: tag(1, TAGBOX),
                           b4: tag(0, TAGVIRTUAL), b5: tag(1, TAGVIRTUAL)}
-    assert numb5.nums == [tag(0, TAGBOX), tag(0, TAGVIRTUAL),
-                                          tag(1, TAGVIRTUAL)]
-    assert numb5.prev is numb4
+    assert list(numb5.nums) == [tag(0, TAGBOX), tag(0, TAGVIRTUAL),
+                                                tag(1, TAGVIRTUAL)]
+    assert numb5.prev == numb4
 
 def test_ResumeDataLoopMemo_number_boxes():
     memo = ResumeDataLoopMemo(FakeMetaInterpStaticData())

Modified: pypy/trunk/pypy/jit/metainterp/virtualizable.py
==============================================================================
--- pypy/trunk/pypy/jit/metainterp/virtualizable.py	(original)
+++ pypy/trunk/pypy/jit/metainterp/virtualizable.py	Sat Nov 13 19:11:37 2010
@@ -100,48 +100,48 @@
                     i = i + 1
             assert len(boxes) == i + 1
         #
-        def write_from_resume_data_partial(virtualizable, reader, nums):
+        def write_from_resume_data_partial(virtualizable, reader, numb):
             # Load values from the reader (see resume.py) described by
             # the list of numbers 'nums', and write them in their proper
             # place in the 'virtualizable'.  This works from the end of
             # the list and returns the index in 'nums' of the start of
             # the virtualizable data found, allowing the caller to do
             # further processing with the start of the list.
-            i = len(nums) - 1
+            i = len(numb.nums) - 1
             assert i >= 0
             for ARRAYITEMTYPE, fieldname in unroll_array_fields_rev:
                 lst = getattr(virtualizable, fieldname)
                 for j in range(getlength(lst)-1, -1, -1):
                     i -= 1
                     assert i >= 0
-                    x = reader.load_value_of_type(ARRAYITEMTYPE, nums[i])
+                    x = reader.load_value_of_type(ARRAYITEMTYPE, numb.nums[i])
                     setarrayitem(lst, j, x)
             for FIELDTYPE, fieldname in unroll_static_fields_rev:
                 i -= 1
                 assert i >= 0
-                x = reader.load_value_of_type(FIELDTYPE, nums[i])
+                x = reader.load_value_of_type(FIELDTYPE, numb.nums[i])
                 setattr(virtualizable, fieldname, x)
             return i
         #
-        def load_list_of_boxes(virtualizable, reader, nums):
+        def load_list_of_boxes(virtualizable, reader, numb):
             # Uses 'virtualizable' only to know the length of the arrays;
             # does not write anything into it.  The returned list is in
             # the format expected of virtualizable_boxes, so it ends in
             # the virtualizable itself.
-            i = len(nums) - 1
+            i = len(numb.nums) - 1
             assert i >= 0
-            boxes = [reader.decode_box_of_type(self.VTYPEPTR, nums[i])]
+            boxes = [reader.decode_box_of_type(self.VTYPEPTR, numb.nums[i])]
             for ARRAYITEMTYPE, fieldname in unroll_array_fields_rev:
                 lst = getattr(virtualizable, fieldname)
                 for j in range(getlength(lst)-1, -1, -1):
                     i -= 1
                     assert i >= 0
-                    box = reader.decode_box_of_type(ARRAYITEMTYPE, nums[i])
+                    box = reader.decode_box_of_type(ARRAYITEMTYPE,numb.nums[i])
                     boxes.append(box)
             for FIELDTYPE, fieldname in unroll_static_fields_rev:
                 i -= 1
                 assert i >= 0
-                box = reader.decode_box_of_type(FIELDTYPE, nums[i])
+                box = reader.decode_box_of_type(FIELDTYPE, numb.nums[i])
                 boxes.append(box)
             boxes.reverse()
             return boxes



More information about the Pypy-commit mailing list