Author: Carl Friedrich Bolz <cfb...@gmx.de>
Branch: optinfo-into-bridges
Changeset: r87810:3170ca56ec4a
Date: 2016-10-14 18:09 +0200
http://bitbucket.org/pypy/pypy/changeset/3170ca56ec4a/

Log:    make use of the full three bytes that resumecode uses by allowing
        more values

        this saves memory for encoding integer constants

diff --git a/rpython/jit/metainterp/optimizeopt/bridgeopt.py 
b/rpython/jit/metainterp/optimizeopt/bridgeopt.py
--- a/rpython/jit/metainterp/optimizeopt/bridgeopt.py
+++ b/rpython/jit/metainterp/optimizeopt/bridgeopt.py
@@ -81,9 +81,9 @@
             if index == -1:
                 # XXX XXX XXX fix length!
                 continue # just skip it, if the descr is not encodable
-            numb_state.append_short(tag_box(box1, liveboxes_from_env, memo))
+            numb_state.append_int(tag_box(box1, liveboxes_from_env, memo))
             numb_state.append_int(index)
-            numb_state.append_short(tag_box(box2, liveboxes_from_env, memo))
+            numb_state.append_int(tag_box(box2, liveboxes_from_env, memo))
     else:
         numb_state.append_int(0)
 
diff --git a/rpython/jit/metainterp/resume.py b/rpython/jit/metainterp/resume.py
--- a/rpython/jit/metainterp/resume.py
+++ b/rpython/jit/metainterp/resume.py
@@ -13,6 +13,7 @@
 from rpython.rtyper.rclass import OBJECTPTR
 from rpython.jit.metainterp.walkvirtual import VirtualVisitor
 from rpython.jit.metainterp import resumecode
+TagOverflow = resumecode.TagOverflow
 
 
 # Logic to encode the chain of frames and the state of the boxes at a
@@ -124,18 +125,14 @@
 
 TAGMASK = 3
 
-class TagOverflow(Exception):
-    pass
-
 def tag(value, tagbits):
     assert 0 <= tagbits <= 3
-    sx = value >> 13
-    if sx != 0 and sx != -1:
-        raise TagOverflow
-    return rffi.r_short(value<<2|tagbits)
+    result = value<<2|tagbits
+    if not resumecode.integer_fits(result):
+        raise resumecode.TagOverflow
+    return result
 
 def untag(value):
-    value = rarithmetic.widen(value)
     tagbits = value & TAGMASK
     return value >> 2, tagbits
 
@@ -249,7 +246,7 @@
                     tagged = tag(num_boxes, TAGBOX)
                     num_boxes += 1
                 liveboxes[box] = tagged
-            numb_state.append_short(tagged)
+            numb_state.append_int(tagged)
         numb_state.num_boxes = num_boxes
         numb_state.num_virtuals = num_virtuals
 
@@ -559,8 +556,8 @@
                 fieldbox = optimizer.get_box_replacement(fieldbox)
                 #descr, box, fieldbox, itemindex = pending_setfields[i]
                 lldescr = annlowlevel.cast_instance_to_base_ptr(descr)
-                num = self._gettagged(box)
-                fieldnum = self._gettagged(fieldbox)
+                num = rffi.r_short(self._gettagged(box))
+                fieldnum = rffi.r_short(self._gettagged(fieldbox))
                 # the index is limited to 2147483647 (64-bit machines only)
                 if itemindex > 2147483647:
                     raise TagOverflow
diff --git a/rpython/jit/metainterp/resumecode.py 
b/rpython/jit/metainterp/resumecode.py
--- a/rpython/jit/metainterp/resumecode.py
+++ b/rpython/jit/metainterp/resumecode.py
@@ -1,4 +1,3 @@
-
 """ Resume bytecode. It goes as following:
 
   # ----- resume section
@@ -19,11 +18,24 @@
 
   # ----- optimization section
   <more code>                                      further sections according 
to bridgeopt.py
+
 """
 
 from rpython.rtyper.lltypesystem import rffi, lltype
 from rpython.rlib import objectmodel
 
+class TagOverflow(Exception):
+    pass
+
+def integer_fits(item):
+    item *= 2
+    if item < 0:
+       item = ~item
+    # we can fit up to 22 content bits into 1-3 bytes (24 bits, with 2 
continuation
+    # bits)
+    return item < 2 ** 22
+
+
 NUMBERINGP = lltype.Ptr(lltype.GcForwardReference())
 NUMBERING = lltype.GcStruct('Numbering',
                             ('code', lltype.Array(rffi.UCHAR)))
@@ -31,10 +43,13 @@
 NULL_NUMBER = lltype.nullptr(NUMBERING)
 
 def append_numbering(lst, item):
-    item = rffi.cast(lltype.Signed, item)
+    # item is just an int
+    assert isinstance(item, int)
+    if not integer_fits(item):
+        raise TagOverflow
     item *= 2
     if item < 0:
-        item = -1 - item
+       item = ~item
 
     assert item >= 0
     if item < 2**7:
@@ -43,7 +58,7 @@
         lst.append(rffi.cast(rffi.UCHAR, item | 0x80))
         lst.append(rffi.cast(rffi.UCHAR, item >> 7))
     else:
-        assert item < 2**16
+        assert item < 2**22
         lst.append(rffi.cast(rffi.UCHAR, item | 0x80))
         lst.append(rffi.cast(rffi.UCHAR, (item >> 7) | 0x80))
         lst.append(rffi.cast(rffi.UCHAR, item >> 14))
@@ -80,20 +95,15 @@
     return l
 
 class Writer(object):
-    def __init__(self, size):
+    def __init__(self, size=0):
         self.current = objectmodel.newlist_hint(3 * size)
         self.grow(size)
         self.items = 0
 
-    def append_short(self, item):
+    def append_int(self, item):
         self.items += 1
         append_numbering(self.current, item)
 
-    def append_int(self, item):
-        short = rffi.cast(rffi.SHORT, item)
-        assert rffi.cast(lltype.Signed, short) == item
-        return self.append_short(short)
-
     def create_numbering(self):
         numb = lltype.malloc(NUMBERING, len(self.current))
         for i, elt in enumerate(self.current):
@@ -105,12 +115,19 @@
 
     def patch_current_size(self, index):
         # mess :-(
-        assert rffi.cast(lltype.Signed, self.current[index]) == 0
+        assert self.current[index] == 0
         l = []
         append_numbering(l, self.items)
         self.current = l + self.current[1:]
 
 
+def create_numbering(l):
+    w = Writer()
+    for item in l:
+        w.append_int(item)
+    return w.create_numbering()
+
+
 class Reader(object):
     def __init__(self, code):
         self.code = code
diff --git a/rpython/jit/metainterp/test/test_resume.py 
b/rpython/jit/metainterp/test/test_resume.py
--- a/rpython/jit/metainterp/test/test_resume.py
+++ b/rpython/jit/metainterp/test/test_resume.py
@@ -111,10 +111,10 @@
 
 
 def test_tag():
-    assert tag(3, 1) == rffi.r_short(3<<2|1)
-    assert tag(-3, 2) == rffi.r_short(-3<<2|2)
-    assert tag((1<<13)-1, 3) == rffi.r_short(((1<<15)-1)|3)
-    assert tag(-1<<13, 3) == rffi.r_short((-1<<15)|3)
+    assert tag(3, 1) == 3<<2|1
+    assert tag(-3, 2) == -3<<2|2
+    assert tag((1<<13)-1, 3) == ((1<<15)-1)|3
+    assert tag(-1<<13, 3) ==(-1<<15)|3
     py.test.raises(AssertionError, tag, 3, 5)
     py.test.raises(TagOverflow, tag, 1<<13, 0)
     py.test.raises(TagOverflow, tag, (1<<13)+1, 0)
diff --git a/rpython/jit/metainterp/test/test_resumecode.py 
b/rpython/jit/metainterp/test/test_resumecode.py
--- a/rpython/jit/metainterp/test/test_resumecode.py
+++ b/rpython/jit/metainterp/test/test_resumecode.py
@@ -1,9 +1,19 @@
+import pytest
 from rpython.jit.metainterp.resumecode import create_numbering,\
-    unpack_numbering, Reader, Writer
+    unpack_numbering, Reader, Writer, TagOverflow
 from rpython.rtyper.lltypesystem import lltype
 
 from hypothesis import strategies, given, example
 
+def test_tag_overflow():
+    w = Writer()
+    with pytest.raises(TagOverflow):
+        w.append_int(2**21)
+    with pytest.raises(TagOverflow):
+        w.append_int(-2**22)
+    with pytest.raises(TagOverflow):
+        w.append_int(-2**21-1)
+
 examples = [
     [1, 2, 3, 4, 257, 10000, 13, 15],
     [1, 2, 3, 4],
@@ -12,7 +22,7 @@
 ]
 
 def hypothesis_and_examples(func):
-    func = given(strategies.lists(strategies.integers(-2**15, 2**15-1)))(func)
+    func = given(strategies.lists(strategies.integers(-2**21, 2**21-1)))(func)
     for ex in examples:
         func = example(ex)(func)
     return func
@@ -60,3 +70,5 @@
         n = w.create_numbering()
         assert unpack_numbering(n)[1:] == l
         assert unpack_numbering(n)[0] == middle + 1
+
+
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to