Author: Armin Rigo <ar...@tunes.org>
Branch: 
Changeset: r67929:837dea310b4d
Date: 2013-11-10 14:48 +0100
http://bitbucket.org/pypy/pypy/changeset/837dea310b4d/

Log:    Fix the bogus complexity of marshal dumping "long" objects

diff --git a/pypy/module/marshal/test/test_marshalimpl.py 
b/pypy/module/marshal/test/test_marshalimpl.py
--- a/pypy/module/marshal/test/test_marshalimpl.py
+++ b/pypy/module/marshal/test/test_marshalimpl.py
@@ -56,3 +56,29 @@
 class AppTestMarshalSmallLong(AppTestMarshalMore):
     spaceconfig = dict(usemodules=('array',),
                        **{"objspace.std.withsmalllong": True})
+
+
+def test_long_more(space):
+    import marshal, struct
+
+    class FakeM:
+        def __init__(self):
+            self.seen = []
+        def start(self, code):
+            self.seen.append(code)
+        def put_int(self, value):
+            self.seen.append(struct.pack("i", value))
+        def put_short(self, value):
+            self.seen.append(struct.pack("h", value))
+
+    def _marshal_check(x):
+        expected = marshal.dumps(long(x))
+        w_obj = space.wraplong(x)
+        m = FakeM()
+        space.marshal_w(w_obj, m)
+        assert ''.join(m.seen) == expected
+
+    for sign in [1L, -1L]:
+        for i in range(100):
+            _marshal_check(sign * ((1L << i) - 1L))
+            _marshal_check(sign * (1L << i))
diff --git a/pypy/objspace/std/marshal_impl.py 
b/pypy/objspace/std/marshal_impl.py
--- a/pypy/objspace/std/marshal_impl.py
+++ b/pypy/objspace/std/marshal_impl.py
@@ -207,20 +207,20 @@
 
 def marshal_w__Long(space, w_long, m):
     from rpython.rlib.rbigint import rbigint
+    from rpython.rlib.rarithmetic import r_ulonglong
     m.start(TYPE_LONG)
     SHIFT = 15
     MASK = (1 << SHIFT) - 1
     num = w_long.num
     sign = num.sign
     num = num.abs()
-    ints = []
-    while num.tobool():
-        next = intmask(num.uintmask() & MASK)
-        ints.append(next)
-        num = num.rshift(SHIFT)
-    m.put_int(len(ints) * sign)
-    for i in ints:
-        m.put_short(i)
+    total_length = (num.bit_length() + (SHIFT - 1)) / SHIFT
+    m.put_int(total_length * sign)
+    bigshiftcount = r_ulonglong(0)
+    for i in range(total_length):
+        next = num.abs_rshift_and_mask(bigshiftcount, MASK)
+        m.put_short(next)
+        bigshiftcount += SHIFT
 
 def unmarshal_Long(space, u, tc):
     from rpython.rlib.rbigint import rbigint
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to