Commits

Maciej Fijalkowski committed f95aaab

IN-PROGRESS string-char concat not upgrading char to string. Give up for now

Comments (0)

Files changed (8)

pypy/jit/codewriter/effectinfo.py

     OS_STR2UNICODE              = 2    # "str.str2unicode"
     #
     OS_STR_CONCAT               = 22   # "stroruni.concat"
-    OS_STR_SLICE                = 23   # "stroruni.slice"
-    OS_STR_EQUAL                = 24   # "stroruni.equal"
-    OS_STREQ_SLICE_CHECKNULL    = 25   # s2!=NULL and s1[x:x+length]==s2
-    OS_STREQ_SLICE_NONNULL      = 26   # s1[x:x+length]==s2   (assert s2!=NULL)
-    OS_STREQ_SLICE_CHAR         = 27   # s1[x:x+length]==char
-    OS_STREQ_NONNULL            = 28   # s1 == s2    (assert s1!=NULL,s2!=NULL)
-    OS_STREQ_NONNULL_CHAR       = 29   # s1 == char  (assert s1!=NULL)
-    OS_STREQ_CHECKNULL_CHAR     = 30   # s1!=NULL and s1==char
-    OS_STREQ_LENGTHOK           = 31   # s1 == s2    (assert len(s1)==len(s2))
+    OS_STR_CONCAT_CHAR          = 23   # "stroruni.concatchar"
+    OS_STR_SLICE                = 24   # "stroruni.slice"
+    OS_STR_EQUAL                = 25   # "stroruni.equal"
+    OS_STREQ_SLICE_CHECKNULL    = 26   # s2!=NULL and s1[x:x+length]==s2
+    OS_STREQ_SLICE_NONNULL      = 27   # s1[x:x+length]==s2   (assert s2!=NULL)
+    OS_STREQ_SLICE_CHAR         = 28   # s1[x:x+length]==char
+    OS_STREQ_NONNULL            = 29   # s1 == s2    (assert s1!=NULL,s2!=NULL)
+    OS_STREQ_NONNULL_CHAR       = 30   # s1 == char  (assert s1!=NULL)
+    OS_STREQ_CHECKNULL_CHAR     = 31   # s1!=NULL and s1==char
+    OS_STREQ_LENGTHOK           = 32   # s1 == s2    (assert len(s1)==len(s2))
     #
     OS_UNI_CONCAT               = 42   #
-    OS_UNI_SLICE                = 43   #
-    OS_UNI_EQUAL                = 44   #
-    OS_UNIEQ_SLICE_CHECKNULL    = 45   #
-    OS_UNIEQ_SLICE_NONNULL      = 46   #
-    OS_UNIEQ_SLICE_CHAR         = 47   #
-    OS_UNIEQ_NONNULL            = 48   #   the same for unicode
-    OS_UNIEQ_NONNULL_CHAR       = 49   #   (must be the same amount as for
-    OS_UNIEQ_CHECKNULL_CHAR     = 50   #   STR, in the same order)
-    OS_UNIEQ_LENGTHOK           = 51   #
+    OS_UNI_CONCAT_CHAR          = 43   #
+    OS_UNI_SLICE                = 44   #
+    OS_UNI_EQUAL                = 45   #
+    OS_UNIEQ_SLICE_CHECKNULL    = 46   #
+    OS_UNIEQ_SLICE_NONNULL      = 47   #
+    OS_UNIEQ_SLICE_CHAR         = 48   #
+    OS_UNIEQ_NONNULL            = 49   #   the same for unicode
+    OS_UNIEQ_NONNULL_CHAR       = 50   #   (must be the same amount as for
+    OS_UNIEQ_CHECKNULL_CHAR     = 51   #   STR, in the same order)
+    OS_UNIEQ_LENGTHOK           = 52   #
     _OS_offset_uni              = OS_UNI_CONCAT - OS_STR_CONCAT
     #
     OS_LIBFFI_CALL              = 62

pypy/jit/codewriter/jtransform.py

         SoU = args[0].concretetype     # Ptr(STR) or Ptr(UNICODE)
         if SoU.TO == rstr.STR:
             dict = {"stroruni.concat": EffectInfo.OS_STR_CONCAT,
+                    "stroruni.concatchar": EffectInfo.OS_STR_CONCAT_CHAR,
                     "stroruni.slice":  EffectInfo.OS_STR_SLICE,
                     "stroruni.equal":  EffectInfo.OS_STR_EQUAL,
                     }

pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py

         """
         self.optimize_strunicode_loop(ops, expected)
 
+    def test_str_concat_char(self):
+        ops = """
+        [p1, i2]
+        p3 = call(0, p1, i2, descr=strconcatchardescr)
+        jump(p3, i2)
+        """
+        expected = """
+        [p1, i0]
+        i1 = strlen(p1)
+        i3 = int_add(i1, 1)
+        p3 = newstr(i3)
+        copystrcontent(p1, p3, 0, 0, i1)
+        strsetitem(p1, i1, i0)
+        jump(p3, i0)
+        """
+        self.optimize_strunicode_loop(ops, expected)
+
     def test_str_concat_vstr2_str(self):
         ops = """
         [i0, i1, p2]

pypy/jit/metainterp/optimizeopt/test/test_util.py

 
     for _name, _os in [
         ('strconcatdescr',               'OS_STR_CONCAT'),
+        ('strconcatchardescr',           'OS_STR_CONCAT_CHAR'),
         ('strslicedescr',                'OS_STR_SLICE'),
         ('strequaldescr',                'OS_STR_EQUAL'),
         ('streq_slice_checknull_descr',  'OS_STREQ_SLICE_CHECKNULL'),

pypy/jit/metainterp/optimizeopt/vstring.py

     def _make_virtual(self, modifier):
         return modifier.make_vstrconcat(self.mode is mode_unicode)
 
-
 class VStringSliceValue(VAbstractStringValue):
     """A slice."""
     _attrs_ = ('vstr', 'vstart', 'vlength')

pypy/rpython/lltypesystem/rstr.py

     ll_strconcat.oopspec = 'stroruni.concat(s1, s2)'
 
     @jit.elidable
+    def ll_strconcat_char(s1, c2):
+        len1 = len(s1.chars)
+        # a single '+' like this is allowed to overflow: it gets
+        # a negative result, and the gc will complain
+        newstr = s1.malloc(len1 + 1)
+        newstr.copy_contents(s1, newstr, 0, 0, len1)
+        newstr.chars[len1] = c2
+        return newstr
+    ll_strconcat_char.oopspec = 'stroruni.concatchar(s1, c2)'
+
+    @jit.elidable
     def ll_strip(s, ch, left, right):
         s_len = len(s.chars)
         if s_len == 0:

pypy/rpython/rstr.py

         hop.exception_cannot_occur()
         return hop.gendirectcall(r_str.ll.ll_contains, v_str, v_chr)
 
+    def rtype_add((r_str, r_chr), hop):
+        string_repr = r_str.repr
+        char_repr = r_chr.char_repr
+        v_str, v_chr = hop.inputargs(string_repr, char_repr)
+        hop.exception_is_here()
+        return hop.gendirectcall(r_str.ll.ll_strconcat_char, v_str, v_chr)
+
 class __extend__(pairtype(AbstractStringRepr, AbstractTupleRepr)):
     def rtype_mod((r_str, r_tuple), hop):
         r_tuple = hop.args_r[1]

pypy/rpython/test/test_rstr.py

 from pypy.rpython.rstr import AbstractLLHelpers
 from pypy.rpython.rtyper import TyperError
 from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin
+from pypy.rpython.test.test_llinterp import get_interpreter
 
 
 def test_parse_fmt():
         res = self.interpret(f, [5])
         assert res == 0
 
+    def test_char_addition_does_not_promote(self):
+        const = self.const
+        constchar = self.constchar
+        
+        def f(n):
+            return const("abc") + constchar(n)
+
+        interp, graph = get_interpreter(f, [ord('a')])
+        opnames = [op.opname for op in graph.iterblocks().next().operations]
+        assert opnames.count('direct_call') == 1
+        assert self.ll_to_string(interp.eval_graph(graph, [ord('a')])) == "abca"
 
 class TestOOtype(BaseTestRstr, OORtypeMixin):
     pass
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.