[pypy-svn] r77262 - in pypy/branch/jit-str/pypy: jit/codewriter jit/codewriter/test jit/metainterp jit/metainterp/optimizeopt jit/metainterp/test rpython/lltypesystem

arigo at codespeak.net arigo at codespeak.net
Wed Sep 22 11:52:53 CEST 2010


Author: arigo
Date: Wed Sep 22 11:52:51 2010
New Revision: 77262

Modified:
   pypy/branch/jit-str/pypy/jit/codewriter/support.py
   pypy/branch/jit-str/pypy/jit/codewriter/test/test_jtransform.py
   pypy/branch/jit-str/pypy/jit/metainterp/optimizefindnode.py
   pypy/branch/jit-str/pypy/jit/metainterp/optimizeopt/optimizer.py
   pypy/branch/jit-str/pypy/jit/metainterp/optimizeopt/rewrite.py
   pypy/branch/jit-str/pypy/jit/metainterp/optimizeopt/virtualize.py
   pypy/branch/jit-str/pypy/jit/metainterp/optimizeutil.py
   pypy/branch/jit-str/pypy/jit/metainterp/resume.py
   pypy/branch/jit-str/pypy/jit/metainterp/test/test_string.py
   pypy/branch/jit-str/pypy/jit/metainterp/warmstate.py
   pypy/branch/jit-str/pypy/rpython/lltypesystem/rstr.py
Log:
In-progress.  Add "virtual one-character strings".


Modified: pypy/branch/jit-str/pypy/jit/codewriter/support.py
==============================================================================
--- pypy/branch/jit-str/pypy/jit/codewriter/support.py	(original)
+++ pypy/branch/jit-str/pypy/jit/codewriter/support.py	Wed Sep 22 11:52:51 2010
@@ -275,10 +275,12 @@
 
     # ---------- strings and unicode ----------
 
-    _ll_5_string_copy_contents = ll_rstr.copy_string_contents
-
     _ll_1_str_str2unicode = ll_rstr.LLHelpers.ll_str2unicode
-    _ll_5_unicode_copy_contents = ll_rstr.copy_unicode_contents
+
+    _ll_2_stroruni_concat          = ll_rstr.LLHelpers.ll_strconcat
+    _ll_2_stroruni_slice_startonly = ll_rstr.LLHelpers.ll_stringslice_startonly
+    _ll_3_stroruni_slice_startstop = ll_rstr.LLHelpers.ll_stringslice_startstop
+    _ll_1_stroruni_slice_minusone  = ll_rstr.LLHelpers.ll_stringslice_minusone
 
     # ---------- malloc with del ----------
 

Modified: pypy/branch/jit-str/pypy/jit/codewriter/test/test_jtransform.py
==============================================================================
--- pypy/branch/jit-str/pypy/jit/codewriter/test/test_jtransform.py	(original)
+++ pypy/branch/jit-str/pypy/jit/codewriter/test/test_jtransform.py	Wed Sep 22 11:52:51 2010
@@ -1,3 +1,4 @@
+import py
 import random
 from pypy.objspace.flow.model import FunctionGraph, Block, Link
 from pypy.objspace.flow.model import SpaceOperation, Variable, Constant
@@ -7,6 +8,9 @@
 from pypy.translator.unsimplify import varoftype
 from pypy.jit.codewriter import heaptracker
 
+def const(x):
+    return Constant(x, lltype.typeOf(x))
+
 class FakeRTyper:
     class type_system: name = 'lltypesystem'
     instance_reprs = {}
@@ -67,6 +71,14 @@
     def calldescr_canraise(self, calldescr):
         return False
 
+class FakeBuiltinCallControl:
+    def guess_call_kind(self, op):
+        return 'builtin'
+    def getcalldescr(self, op):
+        return 'calldescr'
+    def calldescr_canraise(self, calldescr):
+        return False
+
 
 def test_optimize_goto_if_not():
     v1 = Variable()
@@ -107,7 +119,7 @@
     assert block.operations == []
     assert block.exitswitch == ('int_gt', v1, v2)
     assert block.exits == exits
-    assert exits[1].args == [Constant(True, lltype.Bool)]
+    assert exits[1].args == [const(True)]
 
 def test_optimize_goto_if_not__unknownop():
     v3 = Variable(); v3.concretetype = lltype.Bool
@@ -159,8 +171,8 @@
            'float_gt': ('float_gt', 'float_lt'),
            }
     v3 = varoftype(lltype.Signed)
-    for v1 in [varoftype(lltype.Signed), Constant(42, lltype.Signed)]:
-        for v2 in [varoftype(lltype.Signed), Constant(43, lltype.Signed)]:
+    for v1 in [varoftype(lltype.Signed), const(42)]:
+        for v2 in [varoftype(lltype.Signed), const(43)]:
             for name1, name2 in ops.items():
                 op = SpaceOperation(name1, [v1, v2], v3)
                 op1 = Transformer(FakeCPU()).rewrite_operation(op)
@@ -177,8 +189,8 @@
 
 def test_symmetric_int_add_ovf():
     v3 = varoftype(lltype.Signed)
-    for v1 in [varoftype(lltype.Signed), Constant(42, lltype.Signed)]:
-        for v2 in [varoftype(lltype.Signed), Constant(43, lltype.Signed)]:
+    for v1 in [varoftype(lltype.Signed), const(42)]:
+        for v2 in [varoftype(lltype.Signed), const(43)]:
             op = SpaceOperation('int_add_nonneg_ovf', [v1, v2], v3)
             oplist = Transformer(FakeCPU()).rewrite_operation(op)
             op0, op1 = oplist
@@ -218,7 +230,7 @@
 def get_direct_call_op(argtypes, restype):
     FUNC = lltype.FuncType(argtypes, restype)
     fnptr = lltype.functionptr(FUNC, "g")    # no graph
-    c_fnptr = Constant(fnptr, concretetype=lltype.typeOf(fnptr))
+    c_fnptr = const(fnptr)
     vars = [varoftype(TYPE) for TYPE in argtypes]
     v_result = varoftype(restype)
     op = SpaceOperation('direct_call', [c_fnptr] + vars, v_result)
@@ -465,7 +477,7 @@
     v1 = varoftype(lltype.Signed)
     v2 = varoftype(lltype.Signed)
     v3 = varoftype(lltype.Bool)
-    c0 = Constant(0, lltype.Signed)
+    c0 = const(0)
     #
     for opname, reducedname in [('int_eq', 'int_is_zero'),
                                 ('int_ne', 'int_is_true')]:
@@ -488,7 +500,7 @@
     v1 = varoftype(rclass.OBJECTPTR)
     v2 = varoftype(rclass.OBJECTPTR)
     v3 = varoftype(lltype.Bool)
-    c0 = Constant(lltype.nullptr(rclass.OBJECT), rclass.OBJECTPTR)
+    c0 = const(lltype.nullptr(rclass.OBJECT))
     #
     for opname, reducedname in [('ptr_eq', 'ptr_iszero'),
                                 ('ptr_ne', 'ptr_nonzero')]:
@@ -511,7 +523,7 @@
     v1 = varoftype(rclass.NONGCOBJECTPTR)
     v2 = varoftype(rclass.NONGCOBJECTPTR)
     v3 = varoftype(lltype.Bool)
-    c0 = Constant(lltype.nullptr(rclass.NONGCOBJECT), rclass.NONGCOBJECTPTR)
+    c0 = const(lltype.nullptr(rclass.NONGCOBJECT))
     #
     for opname, reducedname in [('ptr_eq', 'int_is_zero'),
                                 ('ptr_ne', 'int_is_true')]:
@@ -656,3 +668,83 @@
     oplist = tr.rewrite_operation(op)
     assert oplist[0].opname == 'inline_call_ir_i'
     assert oplist[0].args[0] == 'somejitcode'
+
+def test_str_newstr():
+    c_STR = Constant(rstr.STR, lltype.Void)
+    c_flavor = Constant({'flavor': 'gc'}, lltype.Void)
+    v1 = varoftype(lltype.Signed)
+    v2 = varoftype(lltype.Ptr(rstr.STR))
+    op = SpaceOperation('malloc_varsize', [c_STR, c_flavor, v1], v2)
+    op1 = Transformer().rewrite_operation(op)
+    assert op1.opname == 'newstr'
+    assert op1.args == [v1]
+    assert op1.result == v2
+
+def test_str_concat():
+    py.test.xfail('later')
+    # test that the oopspec is present and correctly transformed
+    PSTR = lltype.Ptr(rstr.STR)
+    FUNC = lltype.FuncType([PSTR, PSTR], PSTR)
+    func = lltype.functionptr(FUNC, 'll_strconcat',
+                              _callable=rstr.LLHelpers.ll_strconcat)
+    v1 = varoftype(PSTR)
+    v2 = varoftype(PSTR)
+    v3 = varoftype(PSTR)
+    op = SpaceOperation('direct_call', [const(func), v1, v2], v3)
+    tr = Transformer(FakeCPU(), FakeBuiltinCallControl())
+    op1 = tr.rewrite_operation(op)
+    assert op1.opname == 'residual_call_r_r'
+    assert list(op1.args[2]) == [v1, v2]
+    assert op1.result == v3
+
+def test_str_stringslice_startonly():
+    # test that the oopspec is present and correctly transformed
+    PSTR = lltype.Ptr(rstr.STR)
+    INT = lltype.Signed
+    FUNC = lltype.FuncType([PSTR, INT], PSTR)
+    func = lltype.functionptr(FUNC, 'll_stringslice_startonly',
+                             _callable=rstr.LLHelpers.ll_stringslice_startonly)
+    v1 = varoftype(PSTR)
+    v2 = varoftype(INT)
+    v3 = varoftype(PSTR)
+    op = SpaceOperation('direct_call', [const(func), v1, v2], v3)
+    tr = Transformer(FakeCPU(), FakeBuiltinCallControl())
+    op1 = tr.rewrite_operation(op)
+    assert op1.opname == 'residual_call_ir_r'
+    assert list(op1.args[2]) == [v2]
+    assert list(op1.args[3]) == [v1]
+    assert op1.result == v3
+
+def test_str_stringslice_startstop():
+    # test that the oopspec is present and correctly transformed
+    PSTR = lltype.Ptr(rstr.STR)
+    INT = lltype.Signed
+    FUNC = lltype.FuncType([PSTR, INT, INT], PSTR)
+    func = lltype.functionptr(FUNC, 'll_stringslice_startstop',
+                             _callable=rstr.LLHelpers.ll_stringslice_startstop)
+    v1 = varoftype(PSTR)
+    v2 = varoftype(INT)
+    v3 = varoftype(INT)
+    v4 = varoftype(PSTR)
+    op = SpaceOperation('direct_call', [const(func), v1, v2, v3], v4)
+    tr = Transformer(FakeCPU(), FakeBuiltinCallControl())
+    op1 = tr.rewrite_operation(op)
+    assert op1.opname == 'residual_call_ir_r'
+    assert list(op1.args[2]) == [v2, v3]
+    assert list(op1.args[3]) == [v1]
+    assert op1.result == v4
+
+def test_str_stringslice_minusone():
+    # test that the oopspec is present and correctly transformed
+    PSTR = lltype.Ptr(rstr.STR)
+    FUNC = lltype.FuncType([PSTR], PSTR)
+    func = lltype.functionptr(FUNC, 'll_stringslice_minusone',
+                              _callable=rstr.LLHelpers.ll_stringslice_minusone)
+    v1 = varoftype(PSTR)
+    v2 = varoftype(PSTR)
+    op = SpaceOperation('direct_call', [const(func), v1], v2)
+    tr = Transformer(FakeCPU(), FakeBuiltinCallControl())
+    op1 = tr.rewrite_operation(op)
+    assert op1.opname == 'residual_call_r_r'
+    assert list(op1.args[2]) == [v1]
+    assert op1.result == v2

Modified: pypy/branch/jit-str/pypy/jit/metainterp/optimizefindnode.py
==============================================================================
--- pypy/branch/jit-str/pypy/jit/metainterp/optimizefindnode.py	(original)
+++ pypy/branch/jit-str/pypy/jit/metainterp/optimizefindnode.py	Wed Sep 22 11:52:51 2010
@@ -172,7 +172,7 @@
 
     find_nodes_PTR_EQ        = find_nodes_no_escape
     find_nodes_PTR_NE        = find_nodes_no_escape
-    find_nodes_INSTANCEOF    = find_nodes_no_escape
+    ##find_nodes_INSTANCEOF    = find_nodes_no_escape
     find_nodes_GUARD_NONNULL = find_nodes_no_escape
     find_nodes_GUARD_ISNULL  = find_nodes_no_escape
 

Modified: pypy/branch/jit-str/pypy/jit/metainterp/optimizeopt/optimizer.py
==============================================================================
--- pypy/branch/jit-str/pypy/jit/metainterp/optimizeopt/optimizer.py	(original)
+++ pypy/branch/jit-str/pypy/jit/metainterp/optimizeopt/optimizer.py	Wed Sep 22 11:52:51 2010
@@ -126,6 +126,12 @@
     def setitem(self, index, value):
         raise NotImplementedError
 
+    def getchar(self):
+        raise NotImplementedError
+
+    def setchar(self, charvalue):
+        raise NotImplementedError
+
 class ConstantValue(OptValue):
     def __init__(self, box):
         self.make_constant(box)

Modified: pypy/branch/jit-str/pypy/jit/metainterp/optimizeopt/rewrite.py
==============================================================================
--- pypy/branch/jit-str/pypy/jit/metainterp/optimizeopt/rewrite.py	(original)
+++ pypy/branch/jit-str/pypy/jit/metainterp/optimizeopt/rewrite.py	Wed Sep 22 11:52:51 2010
@@ -307,17 +307,17 @@
     def optimize_PTR_EQ(self, op):
         self._optimize_oois_ooisnot(op, False)
 
-    def optimize_INSTANCEOF(self, op):
-        value = self.getvalue(op.args[0])
-        realclassbox = value.get_constant_class(self.optimizer.cpu)
-        if realclassbox is not None:
-            checkclassbox = self.optimizer.cpu.typedescr2classbox(op.descr)
-            result = self.optimizer.cpu.ts.subclassOf(self.optimizer.cpu,
-                                                      realclassbox, 
-                                                      checkclassbox)
-            self.make_constant_int(op.result, result)
-            return
-        self.emit_operation(op)
+##    def optimize_INSTANCEOF(self, op):
+##        value = self.getvalue(op.args[0])
+##        realclassbox = value.get_constant_class(self.optimizer.cpu)
+##        if realclassbox is not None:
+##            checkclassbox = self.optimizer.cpu.typedescr2classbox(op.descr)
+##            result = self.optimizer.cpu.ts.subclassOf(self.optimizer.cpu,
+##                                                      realclassbox, 
+##                                                      checkclassbox)
+##            self.make_constant_int(op.result, result)
+##            return
+##        self.emit_operation(op)
 
 optimize_ops = _findall(OptRewrite, 'optimize_')
         

Modified: pypy/branch/jit-str/pypy/jit/metainterp/optimizeopt/virtualize.py
==============================================================================
--- pypy/branch/jit-str/pypy/jit/metainterp/optimizeopt/virtualize.py	(original)
+++ pypy/branch/jit-str/pypy/jit/metainterp/optimizeopt/virtualize.py	Wed Sep 22 11:52:51 2010
@@ -188,12 +188,43 @@
                 itemboxes.append(itemvalue.get_key_box())
             modifier.register_virtual_fields(self.keybox, itemboxes)
             for itemvalue in self._items:
-                if itemvalue is not self.constvalue:
-                    itemvalue.get_args_for_fail(modifier)
+                itemvalue.get_args_for_fail(modifier)
 
     def _make_virtual(self, modifier):
         return modifier.make_varray(self.arraydescr)
 
+class VStringLength1Value(AbstractVirtualValue):
+
+    def __init__(self, optimizer, keybox, source_op=None):
+        AbstractVirtualValue.__init__(self, optimizer, keybox, source_op)
+        self._char = CVAL_ZERO
+
+    def getchar(self):
+        return self._char
+
+    def setchar(self, charvalue):
+        assert isinstance(charvalue, OptValue)
+        self._char = charvalue
+
+    def _really_force(self):
+        assert self.source_op is not None
+        newoperations = self.optimizer.newoperations
+        newoperations.append(self.source_op)
+        self.box = box = self.source_op.result
+        charbox = self._char.force_box()
+        op = ResOperation(rop.STRSETITEM,
+                          [box, ConstInt(0), charbox], None)
+        newoperations.append(op)
+
+    def get_args_for_fail(self, modifier):
+        if self.box is None and not modifier.already_seen_virtual(self.keybox):
+            charboxes = [self._char.get_key_box()]
+            modifier.register_virtual_fields(self.keybox, charboxes)
+            self._char.get_args_for_fail(modifier)
+
+    def _make_virtual(self, modifier):
+        return modifier.make_vstring()
+
 class __extend__(SpecNode):
     def setup_virtual_node(self, optimizer, box, newinputargs):
         raise NotImplementedError
@@ -282,6 +313,11 @@
         self.make_equal_to(box, vvalue)
         return vvalue
 
+    def make_vstring_length1(self, box, source_op=None):
+        vvalue = VStringLength1Value(self.optimizer, box, source_op)
+        self.make_equal_to(box, vvalue)
+        return vvalue
+
     def optimize_JUMP(self, op):
         orgop = self.optimizer.loop.operations[-1]
         exitargs = []
@@ -358,8 +394,8 @@
 
     def optimize_SETFIELD_GC(self, op):
         value = self.getvalue(op.args[0])
-        fieldvalue = self.getvalue(op.args[1])
         if value.is_virtual():
+            fieldvalue = self.getvalue(op.args[1])
             value.setfield(op.descr, fieldvalue)
         else:
             value.ensure_nonnull()
@@ -444,6 +480,44 @@
         self.emit_operation(ResOperation(rop.CALL, op.args[1:], op.result,
                                          descr))
 
+    def optimize_NEWSTR(self, op):
+        length_box = self.get_constant_box(op.args[0])
+        if length_box and length_box.getint() == 1:     # NEWSTR(1)
+            # if the original 'op' did not have a ConstInt as argument,
+            # build a new one with the ConstInt argument
+            if not isinstance(op.args[0], ConstInt):
+                op = ResOperation(rop.NEWSTR, [CONST_1], op.result)
+            self.make_vstring_length1(op.result, op)
+        else:
+            self.emit_operation(op)
+
+    def optimize_STRSETITEM(self, op):
+        value = self.getvalue(op.args[0])
+        if value.is_virtual():
+            charvalue = self.getvalue(op.args[2])
+            value.setchar(charvalue)
+        else:
+            value.ensure_nonnull()
+            self.emit_operation(op)
+
+    def optimize_STRGETITEM(self, op):
+        value = self.getvalue(op.args[0])
+        if value.is_virtual():
+            charvalue = value.getchar()
+            assert charvalue is not None
+            self.make_equal_to(op.result, charvalue)
+        else:
+            value.ensure_nonnull()
+            self.emit_operation(op)
+
+    def optimize_STRLEN(self, op):
+        value = self.getvalue(op.args[0])
+        if value.is_virtual():
+            self.make_constant_int(op.result, 1)
+        else:
+            value.ensure_nonnull()
+            self.emit_operation(op)
+
     def propagate_forward(self, op):
         opnum = op.opnum
         for value, func in optimize_ops:

Modified: pypy/branch/jit-str/pypy/jit/metainterp/optimizeutil.py
==============================================================================
--- pypy/branch/jit-str/pypy/jit/metainterp/optimizeutil.py	(original)
+++ pypy/branch/jit-str/pypy/jit/metainterp/optimizeutil.py	Wed Sep 22 11:52:51 2010
@@ -14,6 +14,11 @@
 
 def _findall(Class, name_prefix):
     result = []
+    for name in dir(Class):
+        if name.startswith(name_prefix):
+            opname = name[len(name_prefix):]
+            if opname.isupper():
+                assert hasattr(resoperation.rop, opname)
     for value, name in resoperation.opname.items():
         if hasattr(Class, name_prefix + name):
             result.append((value, getattr(Class, name_prefix + name)))

Modified: pypy/branch/jit-str/pypy/jit/metainterp/resume.py
==============================================================================
--- pypy/branch/jit-str/pypy/jit/metainterp/resume.py	(original)
+++ pypy/branch/jit-str/pypy/jit/metainterp/resume.py	Wed Sep 22 11:52:51 2010
@@ -253,6 +253,9 @@
     def make_varray(self, arraydescr):
         return VArrayInfo(arraydescr)
 
+    def make_vstring(self):
+        return VStringInfo()
+
     def register_virtual_fields(self, virtualbox, fieldboxes):
         tagged = self.liveboxes_from_env.get(virtualbox, UNASSIGNEDVIRTUAL)
         self.liveboxes[virtualbox] = tagged
@@ -486,6 +489,27 @@
         for i in self.fieldnums:
             debug_print("\t\t", str(untag(i)))
 
+class VStringInfo(AbstractVirtualInfo):
+    def __init__(self):
+        pass
+        #self.fieldnums = ...
+
+    @specialize.argtype(1)
+    def allocate(self, decoder):
+        length = len(self.fieldnums)
+        return decoder.allocate_string(length)
+
+    @specialize.argtype(1)
+    def setfields(self, decoder, string):
+        length = len(self.fieldnums)
+        for i in range(length):
+            decoder.strsetitem(string, i, self.fieldnums[i])
+
+    def debug_prints(self):
+        debug_print("\tvstringinfo")
+        for i in self.fieldnums:
+            debug_print("\t\t", str(untag(i)))
+
 # ____________________________________________________________
 
 class AbstractResumeDataReader(object):
@@ -622,6 +646,9 @@
         return self.metainterp.execute_and_record(rop.NEW_ARRAY,
                                                   arraydescr, ConstInt(length))
 
+    def allocate_string(self, length):
+        return self.metainterp.execute_and_record(rop.NEWSTR, ConstInt(length))
+
     def setfield(self, descr, structbox, fieldnum):
         if descr.is_pointer_field():
             kind = REF
@@ -839,6 +866,9 @@
     def allocate_array(self, arraydescr, length):
         return self.cpu.bh_new_array(arraydescr, length)
 
+    def allocate_string(self, length):
+        return self.cpu.bh_newstr(length)
+
     def setfield(self, descr, struct, fieldnum):
         if descr.is_pointer_field():
             newvalue = self.decode_ref(fieldnum)

Modified: pypy/branch/jit-str/pypy/jit/metainterp/test/test_string.py
==============================================================================
--- pypy/branch/jit-str/pypy/jit/metainterp/test/test_string.py	(original)
+++ pypy/branch/jit-str/pypy/jit/metainterp/test/test_string.py	Wed Sep 22 11:52:51 2010
@@ -1,5 +1,5 @@
 import py
-from pypy.rlib.jit import JitDriver
+from pypy.rlib.jit import JitDriver, dont_look_inside, we_are_jitted
 from pypy.jit.codewriter.policy import StopAtXPolicy
 from pypy.rpython.ootypesystem import ootype
 from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
@@ -72,6 +72,104 @@
         res = self.meta_interp(f, [6, 10])
         assert res == 6
 
+    def test_char2string_pure(self):
+        for dochr in [chr, ]: #unichr]:
+            jitdriver = JitDriver(greens = [], reds = ['n'])
+            @dont_look_inside
+            def escape(x):
+                pass
+            def f(n):
+                while n > 0:
+                    jitdriver.can_enter_jit(n=n)
+                    jitdriver.jit_merge_point(n=n)
+                    s = dochr(n)
+                    if not we_are_jitted():
+                        s += s     # forces to be a string
+                    if n > 100:
+                        escape(s)
+                    n -= 1
+                return 42
+            self.meta_interp(f, [6])
+            self.check_loops(newstr=0, strsetitem=0, strlen=0,
+                             newunicode=0, unicodesetitem=0, unicodelen=0)
+
+    def test_char2string_escape(self):
+        for dochr in [chr, ]: #unichr]:
+            jitdriver = JitDriver(greens = [], reds = ['n', 'total'])
+            @dont_look_inside
+            def escape(x):
+                return ord(x[0])
+            def f(n):
+                total = 0
+                while n > 0:
+                    jitdriver.can_enter_jit(n=n, total=total)
+                    jitdriver.jit_merge_point(n=n, total=total)
+                    s = dochr(n)
+                    if not we_are_jitted():
+                        s += s    # forces to be a string
+                    total += escape(s)
+                    n -= 1
+                return total
+            res = self.meta_interp(f, [6])
+            assert res == 21
+
+    def test_char2string2char(self):
+        for dochr in [chr, ]: #unichr]:
+            jitdriver = JitDriver(greens = [], reds = ['m', 'total'])
+            def f(m):
+                total = 0
+                while m > 0:
+                    jitdriver.can_enter_jit(m=m, total=total)
+                    jitdriver.jit_merge_point(m=m, total=total)
+                    string = dochr(m)
+                    if m > 100:
+                        string += string    # forces to be a string
+                    # read back the character
+                    c = string[0]
+                    total += ord(c)
+                    m -= 1
+                return total
+            res = self.meta_interp(f, [6])
+            assert res == 21
+            self.check_loops(newstr=0, strgetitem=0, strsetitem=0, strlen=0,
+                             newunicode=0, unicodegetitem=0, unicodesetitem=0,
+                             unicodelen=0)
+
+    def test_slice_startonly(self):
+        if 1:     # xxx unicode
+            jitdriver = JitDriver(greens = [], reds = ['m', 'total'])
+            def f(m):
+                total = 0
+                while m >= 0:
+                    jitdriver.can_enter_jit(m=m, total=total)
+                    jitdriver.jit_merge_point(m=m, total=total)
+                    string = 's0dgkwn349tXOGIEQR!'[m:]
+                    c = string[2*m]
+                    total += ord(c)
+                    m -= 1
+                return total
+            res = self.meta_interp(f, [6])
+            assert res == sum(map(ord, 'sgn9OE!'))
+            self.check_loops(call=0, call_pure=0,
+                             newstr=0, strgetitem=1, strsetitem=0, strlen=0)
+
+    def test_strconcat_pure(self):
+        for dochr in [chr, ]: #unichr]:
+            @dont_look_inside
+            def escape(x):
+                pass
+            def f(n, m):
+                s = dochr(n) + dochr(m)
+                if not we_are_jitted():
+                    escape(s)
+                return 42
+            self.interp_operations(f, [65, 66])
+            py.test.xfail()
+            self.check_operations_history(newstr=0, strsetitem=0,
+                                          newunicode=0, unicodesetitem=0,
+                                          call=0, call_pure=0)
+
+
 class TestOOtype(StringTests, OOJitMixin):
     CALL = "oosend"
     CALL_PURE = "oosend_pure"

Modified: pypy/branch/jit-str/pypy/jit/metainterp/warmstate.py
==============================================================================
--- pypy/branch/jit-str/pypy/jit/metainterp/warmstate.py	(original)
+++ pypy/branch/jit-str/pypy/jit/metainterp/warmstate.py	Wed Sep 22 11:52:51 2010
@@ -83,6 +83,9 @@
             return history.ConstFloat(value)
         else:
             return history.BoxFloat(value)
+    elif isinstance(value, (str, unicode)):
+        assert len(value) == 1     # must be a character
+        value = ord(value)
     else:
         value = intmask(value)
     if in_const_box:

Modified: pypy/branch/jit-str/pypy/rpython/lltypesystem/rstr.py
==============================================================================
--- pypy/branch/jit-str/pypy/rpython/lltypesystem/rstr.py	(original)
+++ pypy/branch/jit-str/pypy/rpython/lltypesystem/rstr.py	Wed Sep 22 11:52:51 2010
@@ -65,8 +65,8 @@
         dst = llmemory.cast_ptr_to_adr(dst) + _str_ofs(dststart)
         llmemory.raw_memcopy(src, dst, llmemory.sizeof(CHAR_TP) * length)
     copy_string_contents._always_inline_ = True
-    copy_string_contents.oopspec = (
-        '%s.copy_contents(src, dst, srcstart, dststart, length)' % name)
+    #copy_string_contents.oopspec = (
+    #    '%s.copy_contents(src, dst, srcstart, dststart, length)' % name)
     return func_with_new_name(copy_string_contents, 'copy_%s_contents' % name)
 
 copy_string_contents = _new_copy_contents_fun(STR, Char, 'string')
@@ -326,6 +326,7 @@
         s1.copy_contents(s1, newstr, 0, 0, len1)
         s1.copy_contents(s2, newstr, 0, len1, len2)
         return newstr
+    #ll_strconcat.oopspec = 'stroruni.concat(s1, s2)'
 
     @purefunction
     def ll_strip(s, ch, left, right):
@@ -693,7 +694,6 @@
             i += 1
         return result
 
-    @purefunction
     def ll_stringslice_startonly(s1, start):
         len1 = len(s1.chars)
         newstr = s1.malloc(len1 - start)
@@ -702,8 +702,8 @@
         assert start >= 0
         s1.copy_contents(s1, newstr, start, 0, lgt)
         return newstr
+    ll_stringslice_startonly.oopspec = 'stroruni.slice_startonly(s1, start)'
 
-    @purefunction
     def ll_stringslice_startstop(s1, start, stop):
         if stop >= len(s1.chars):
             if start == 0:
@@ -715,14 +715,16 @@
         assert lgt >= 0
         s1.copy_contents(s1, newstr, start, 0, lgt)
         return newstr
+    ll_stringslice_startstop.oopspec = ('stroruni.slice_startstop(s1, '
+                                            'start, stop)')
 
-    @purefunction
     def ll_stringslice_minusone(s1):
         newlen = len(s1.chars) - 1
         newstr = s1.malloc(newlen)
         assert newlen >= 0
         s1.copy_contents(s1, newstr, 0, 0, newlen)
         return newstr
+    ll_stringslice_minusone.oopspec = 'stroruni.slice_minusone(s1)'
 
     def ll_split_chr(LIST, s, c):
         chars = s.chars



More information about the Pypy-commit mailing list