[pypy-commit] pypy py3.5: special-case 'bytes([single_integer])' or 'bytes((single_int, ))'

arigo pypy.commits at gmail.com
Wed Nov 30 09:23:21 EST 2016


Author: Armin Rigo <arigo at tunes.org>
Branch: py3.5
Changeset: r88763:5aa3b36e215f
Date: 2016-11-30 14:39 +0100
http://bitbucket.org/pypy/pypy/changeset/5aa3b36e215f/

Log:	special-case 'bytes([single_integer])' or 'bytes((single_int,))'

diff --git a/pypy/objspace/std/bytesobject.py b/pypy/objspace/std/bytesobject.py
--- a/pypy/objspace/std/bytesobject.py
+++ b/pypy/objspace/std/bytesobject.py
@@ -1,6 +1,6 @@
 """The builtin bytes implementation"""
 
-from rpython.rlib.jit import we_are_jitted
+from rpython.rlib import jit
 from rpython.rlib.objectmodel import (
     compute_hash, compute_unique_id, import_from_mixin, newlist_hint,
     resizelist_hint, HASH_ALGORITHM)
@@ -529,10 +529,22 @@
     @unwrap_spec(encoding='str_or_None', errors='str_or_None')
     def descr_new(space, w_stringtype, w_source=None, encoding=None,
                   errors=None):
-        if (w_source and space.is_w(space.type(w_source), space.w_bytes) and
-            space.is_w(w_stringtype, space.w_bytes) and encoding is None
-            and errors is None):
-            return w_source
+        if (w_source and space.is_w(w_stringtype, space.w_bytes)
+                and encoding is None and errors is None):
+            # special-case 'bytes(byte_object)'
+            w_srctype = space.type(w_source)
+            if w_srctype is space.w_bytes:
+                return w_source
+            # special-case 'bytes([single_integer])' or 'bytes((single_int,))'
+            # for JITted performance only, when we clearly see the
+            # length of the list/tuple being constant and equal to 1
+            if w_srctype is space.w_list or w_srctype is space.w_tuple:
+                length = space.len_w(w_source)
+                if jit.isconstant(length) and length == 1:
+                    w_item = space.getitem(w_source, space.wrap(0))
+                    value = getbytevalue(space, w_item)
+                    return W_BytesObject(value)
+        #
         value = newbytesdata_w(space, w_source, encoding, errors)
         w_obj = space.allocate_instance(W_BytesObject, w_stringtype)
         W_BytesObject.__init__(w_obj, value)
diff --git a/pypy/objspace/std/test/test_bytesobject.py b/pypy/objspace/std/test/test_bytesobject.py
--- a/pypy/objspace/std/test/test_bytesobject.py
+++ b/pypy/objspace/std/test/test_bytesobject.py
@@ -89,6 +89,13 @@
         assert self.space.listview_bytes(w_bytes) == None
         assert self.space.listview_int(w_bytes) == [97, 98, 99, 100]
 
+    def test_constructor_single_char(self, monkeypatch):
+        from rpython.rlib import jit
+        monkeypatch.setattr(jit, 'isconstant', lambda x: True)
+        space = self.space
+        w_res = space.call_function(space.w_bytes, space.wrap([42]))
+        assert space.str_w(w_res) == '*'
+
 class AppTestBytesObject:
 
     def test_constructor(self):
@@ -97,6 +104,23 @@
         assert bytes(b'abc') == b'abc'
         assert bytes('abc', 'ascii') == b'abc'
         assert bytes(set(b'foo')) in (b'fo', b'of')
+        assert bytes([]) == b''
+        assert bytes([42]) == b'*'
+        assert bytes([0xFC]) == b'\xFC'
+        assert bytes([42, 0xCC]) == b'*\xCC'
+
+    def test_constructor_list_of_objs(self):
+        class X:
+            def __index__(self):
+                return 42
+        class Y:
+            def __int__(self):
+                return 42
+        for obj in [42, X()]:
+            assert bytes([obj]) == b'*'
+            assert bytes([obj, obj, obj]) == b'***'
+        raises(TypeError, bytes, [Y()])
+        raises(TypeError, bytes, [Y(), Y()])
 
     def test_fromhex(self):
         assert bytes.fromhex("abcd") == b'\xab\xcd'


More information about the pypy-commit mailing list