[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