Author: Maciej Fijalkowski <[email protected]>
Branch: string-char-concat
Changeset: r59562:f95aaab180eb
Date: 2012-12-26 14:50 +0200
http://bitbucket.org/pypy/pypy/changeset/f95aaab180eb/
Log: IN-PROGRESS string-char concat not upgrading char to string. Give up
for now
diff --git a/pypy/jit/codewriter/effectinfo.py
b/pypy/jit/codewriter/effectinfo.py
--- a/pypy/jit/codewriter/effectinfo.py
+++ b/pypy/jit/codewriter/effectinfo.py
@@ -23,26 +23,28 @@
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
diff --git a/pypy/jit/codewriter/jtransform.py
b/pypy/jit/codewriter/jtransform.py
--- a/pypy/jit/codewriter/jtransform.py
+++ b/pypy/jit/codewriter/jtransform.py
@@ -1651,6 +1651,7 @@
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,
}
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
b/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
@@ -4099,6 +4099,23 @@
"""
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]
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_util.py
b/pypy/jit/metainterp/optimizeopt/test/test_util.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_util.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_util.py
@@ -210,6 +210,7 @@
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'),
diff --git a/pypy/jit/metainterp/optimizeopt/vstring.py
b/pypy/jit/metainterp/optimizeopt/vstring.py
--- a/pypy/jit/metainterp/optimizeopt/vstring.py
+++ b/pypy/jit/metainterp/optimizeopt/vstring.py
@@ -264,7 +264,6 @@
def _make_virtual(self, modifier):
return modifier.make_vstrconcat(self.mode is mode_unicode)
-
class VStringSliceValue(VAbstractStringValue):
"""A slice."""
_attrs_ = ('vstr', 'vstart', 'vlength')
diff --git a/pypy/rpython/lltypesystem/rstr.py
b/pypy/rpython/lltypesystem/rstr.py
--- a/pypy/rpython/lltypesystem/rstr.py
+++ b/pypy/rpython/lltypesystem/rstr.py
@@ -316,6 +316,17 @@
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:
diff --git a/pypy/rpython/rstr.py b/pypy/rpython/rstr.py
--- a/pypy/rpython/rstr.py
+++ b/pypy/rpython/rstr.py
@@ -542,6 +542,13 @@
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]
diff --git a/pypy/rpython/test/test_rstr.py b/pypy/rpython/test/test_rstr.py
--- a/pypy/rpython/test/test_rstr.py
+++ b/pypy/rpython/test/test_rstr.py
@@ -8,6 +8,7 @@
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():
@@ -1098,6 +1099,17 @@
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
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit