[pypy-svn] r77780 - in pypy/branch/jit-str-unicode/pypy/jit: backend/test backend/x86 backend/x86/test codewriter codewriter/test metainterp metainterp/optimizeopt metainterp/test
arigo at codespeak.net
arigo at codespeak.net
Mon Oct 11 14:26:23 CEST 2010
Author: arigo
Date: Mon Oct 11 14:26:19 2010
New Revision: 77780
Modified:
pypy/branch/jit-str-unicode/pypy/jit/backend/test/runner_test.py
pypy/branch/jit-str-unicode/pypy/jit/backend/test/test_ll_random.py
pypy/branch/jit-str-unicode/pypy/jit/backend/x86/regalloc.py
pypy/branch/jit-str-unicode/pypy/jit/backend/x86/test/test_string.py
pypy/branch/jit-str-unicode/pypy/jit/codewriter/effectinfo.py
pypy/branch/jit-str-unicode/pypy/jit/codewriter/jtransform.py
pypy/branch/jit-str-unicode/pypy/jit/codewriter/test/test_jtransform.py
pypy/branch/jit-str-unicode/pypy/jit/metainterp/history.py
pypy/branch/jit-str-unicode/pypy/jit/metainterp/optimizeopt/intbounds.py
pypy/branch/jit-str-unicode/pypy/jit/metainterp/optimizeopt/rewrite.py
pypy/branch/jit-str-unicode/pypy/jit/metainterp/optimizeopt/string.py
pypy/branch/jit-str-unicode/pypy/jit/metainterp/resume.py
pypy/branch/jit-str-unicode/pypy/jit/metainterp/test/oparser.py
pypy/branch/jit-str-unicode/pypy/jit/metainterp/test/test_optimizefindnode.py
pypy/branch/jit-str-unicode/pypy/jit/metainterp/test/test_optimizeopt.py
pypy/branch/jit-str-unicode/pypy/jit/metainterp/test/test_resume.py
pypy/branch/jit-str-unicode/pypy/jit/metainterp/test/test_string.py
Log:
Check-in. Should be done.
Modified: pypy/branch/jit-str-unicode/pypy/jit/backend/test/runner_test.py
==============================================================================
--- pypy/branch/jit-str-unicode/pypy/jit/backend/test/runner_test.py (original)
+++ pypy/branch/jit-str-unicode/pypy/jit/backend/test/runner_test.py Mon Oct 11 14:26:19 2010
@@ -833,6 +833,23 @@
length_box], 'void')
assert self.look_string(r_box) == "!??cdef?!"
+ def test_copyunicodecontent(self):
+ s_box = self.alloc_unicode(u"abcdef")
+ for s_box in [s_box, s_box.constbox()]:
+ for srcstart_box in [BoxInt(2), ConstInt(2)]:
+ for dststart_box in [BoxInt(3), ConstInt(3)]:
+ for length_box in [BoxInt(4), ConstInt(4)]:
+ for r_box_is_const in [False, True]:
+ r_box = self.alloc_unicode(u"!???????!")
+ if r_box_is_const:
+ r_box = r_box.constbox()
+ self.execute_operation(rop.COPYUNICODECONTENT,
+ [s_box, r_box,
+ srcstart_box,
+ dststart_box,
+ length_box], 'void')
+ assert self.look_unicode(r_box) == u"!??cdef?!"
+
def test_do_unicode_basic(self):
u = self.cpu.bh_newunicode(5)
self.cpu.bh_unicodesetitem(u, 4, 123)
@@ -1227,6 +1244,10 @@
u_box = BoxPtr(lltype.cast_opaque_ptr(llmemory.GCREF, u))
return u_box
+ def look_unicode(self, unicode_box):
+ u = unicode_box.getref(lltype.Ptr(rstr.UNICODE))
+ return u''.join(u.chars)
+
def test_casts(self):
py.test.skip("xxx fix or kill")
Modified: pypy/branch/jit-str-unicode/pypy/jit/backend/test/test_ll_random.py
==============================================================================
--- pypy/branch/jit-str-unicode/pypy/jit/backend/test/test_ll_random.py (original)
+++ pypy/branch/jit-str-unicode/pypy/jit/backend/test/test_ll_random.py Mon Oct 11 14:26:19 2010
@@ -599,7 +599,7 @@
OPERATIONS.append(StrLenOperation(rop.STRLEN))
OPERATIONS.append(UnicodeLenOperation(rop.UNICODELEN))
OPERATIONS.append(CopyStrContentOperation(rop.COPYSTRCONTENT))
- #OPERATIONS.append(CopyUnicodeContentOperation(rop.COPYUNICODECONTENT))
+ OPERATIONS.append(CopyUnicodeContentOperation(rop.COPYUNICODECONTENT))
for i in range(2):
OPERATIONS.append(GuardClassOperation(rop.GUARD_CLASS))
Modified: pypy/branch/jit-str-unicode/pypy/jit/backend/x86/regalloc.py
==============================================================================
--- pypy/branch/jit-str-unicode/pypy/jit/backend/x86/regalloc.py (original)
+++ pypy/branch/jit-str-unicode/pypy/jit/backend/x86/regalloc.py Mon Oct 11 14:26:19 2010
@@ -778,15 +778,11 @@
loc = self.loc(op.getarg(0))
return self._call(op, [loc])
# boehm GC (XXX kill the following code at some point)
- ofs_items, itemsize, ofs = symbolic.get_array_token(rstr.UNICODE, self.translate_support_code)
- if itemsize == 4:
- return self._malloc_varsize(ofs_items, ofs, 2, op.getarg(0),
- op.result)
- elif itemsize == 2:
- return self._malloc_varsize(ofs_items, ofs, 1, op.getarg(0),
- op.result)
- else:
- assert False, itemsize
+ ofs_items, _, ofs = symbolic.get_array_token(rstr.UNICODE,
+ self.translate_support_code)
+ scale = self._get_unicode_item_scale()
+ return self._malloc_varsize(ofs_items, ofs, scale, op.getarg(0),
+ op.result)
def _malloc_varsize(self, ofs_items, ofs_length, scale, v, res_v):
# XXX kill this function at some point
@@ -959,6 +955,12 @@
consider_unicodegetitem = consider_strgetitem
def consider_copystrcontent(self, op):
+ self._consider_copystrcontent(op, is_unicode=False)
+
+ def consider_copyunicodecontent(self, op):
+ self._consider_copystrcontent(op, is_unicode=True)
+
+ def _consider_copystrcontent(self, op, is_unicode):
# compute the source address
args = op.getarglist()
base_loc = self.rm.make_sure_var_in_reg(args[0], args)
@@ -970,7 +972,8 @@
srcaddr_box = TempBox()
forbidden_vars = [args[1], args[3], args[4], srcaddr_box]
srcaddr_loc = self.rm.force_allocate_reg(srcaddr_box, forbidden_vars)
- self._gen_address_inside_string(base_loc, ofs_loc, srcaddr_loc)
+ self._gen_address_inside_string(base_loc, ofs_loc, srcaddr_loc,
+ is_unicode=is_unicode)
# compute the destination address
base_loc = self.rm.make_sure_var_in_reg(args[1], forbidden_vars)
ofs_loc = self.rm.make_sure_var_in_reg(args[3], forbidden_vars)
@@ -980,25 +983,57 @@
forbidden_vars = [args[4], srcaddr_box]
dstaddr_box = TempBox()
dstaddr_loc = self.rm.force_allocate_reg(dstaddr_box, forbidden_vars)
- self._gen_address_inside_string(base_loc, ofs_loc, dstaddr_loc)
+ self._gen_address_inside_string(base_loc, ofs_loc, dstaddr_loc,
+ is_unicode=is_unicode)
+ # compute the length in bytes
+ length_box = args[4]
+ length_loc = self.loc(length_box)
+ if is_unicode:
+ self.rm.possibly_free_var(length_box)
+ forbidden_vars = [srcaddr_box, dstaddr_box]
+ bytes_box = TempBox()
+ bytes_loc = self.rm.force_allocate_reg(bytes_box, forbidden_vars)
+ scale = self._get_unicode_item_scale()
+ if not (isinstance(length_loc, ImmedLoc) or
+ isinstance(length_loc, RegLoc)):
+ self.assembler.mov(length_loc, bytes_loc)
+ length_loc = bytes_loc
+ self.assembler.load_effective_addr(length_loc, 0, scale, bytes_loc)
+ length_box = bytes_box
+ length_loc = bytes_loc
# call memcpy()
- length_loc = self.loc(args[4])
self.rm.before_call()
self.xrm.before_call()
self.assembler._emit_call(imm(self.assembler.memcpy_addr),
[dstaddr_loc, srcaddr_loc, length_loc])
- self.rm.possibly_free_var(args[4])
+ self.rm.possibly_free_var(length_box)
self.rm.possibly_free_var(dstaddr_box)
self.rm.possibly_free_var(srcaddr_box)
- def _gen_address_inside_string(self, baseloc, ofsloc, resloc):
+ def _gen_address_inside_string(self, baseloc, ofsloc, resloc, is_unicode):
cpu = self.assembler.cpu
- ofs_items, itemsize, _ = symbolic.get_array_token(rstr.STR,
+ if is_unicode:
+ ofs_items, _, _ = symbolic.get_array_token(rstr.UNICODE,
+ self.translate_support_code)
+ scale = self._get_unicode_item_scale()
+ else:
+ ofs_items, itemsize, _ = symbolic.get_array_token(rstr.STR,
self.translate_support_code)
- assert itemsize == 1
- self.assembler.load_effective_addr(ofsloc, ofs_items, 0,
+ assert itemsize == 1
+ scale = 0
+ self.assembler.load_effective_addr(ofsloc, ofs_items, scale,
resloc, baseloc)
+ def _get_unicode_item_scale(self):
+ _, itemsize, _ = symbolic.get_array_token(rstr.UNICODE,
+ self.translate_support_code)
+ if itemsize == 4:
+ return 2
+ elif itemsize == 2:
+ return 1
+ else:
+ raise AssertionError("bad unicode item size")
+
def consider_jump(self, op):
assembler = self.assembler
assert self.jump_target_descr is None
Modified: pypy/branch/jit-str-unicode/pypy/jit/backend/x86/test/test_string.py
==============================================================================
--- pypy/branch/jit-str-unicode/pypy/jit/backend/x86/test/test_string.py (original)
+++ pypy/branch/jit-str-unicode/pypy/jit/backend/x86/test/test_string.py Mon Oct 11 14:26:19 2010
@@ -2,8 +2,12 @@
from pypy.jit.metainterp.test import test_string
from pypy.jit.backend.x86.test.test_basic import Jit386Mixin
-class TestString(Jit386Mixin, test_string.StringTests):
+class TestString(Jit386Mixin, test_string.TestLLtype):
# for the individual tests see
# ====> ../../../metainterp/test/test_string.py
- CALL = 'call'
- CALL_PURE = 'call_pure'
+ pass
+
+class TestUnicode(Jit386Mixin, test_string.TestLLtypeUnicode):
+ # for the individual tests see
+ # ====> ../../../metainterp/test/test_string.py
+ pass
Modified: pypy/branch/jit-str-unicode/pypy/jit/codewriter/effectinfo.py
==============================================================================
--- pypy/branch/jit-str-unicode/pypy/jit/codewriter/effectinfo.py (original)
+++ pypy/branch/jit-str-unicode/pypy/jit/codewriter/effectinfo.py Mon Oct 11 14:26:19 2010
@@ -18,19 +18,30 @@
# the 'oopspecindex' field is one of the following values:
OS_NONE = 0 # normal case, no oopspec
OS_ARRAYCOPY = 1 # "list.ll_arraycopy"
- OS_STR_CONCAT = 2 # "stroruni.concat"
- OS_UNI_CONCAT = 3 # "stroruni.concat"
- OS_STR_SLICE = 4 # "stroruni.slice"
- OS_UNI_SLICE = 5 # "stroruni.slice"
- OS_STR_EQUAL = 6 # "stroruni.equal"
- OS_UNI_EQUAL = 7 # "stroruni.equal"
- OS_STREQ_SLICE_CHECKNULL = 8 # s2!=NULL and s1[x:x+length]==s2
- OS_STREQ_SLICE_NONNULL = 9 # s1[x:x+length]==s2 (assert s2!=NULL)
- OS_STREQ_SLICE_CHAR = 10 # s1[x:x+length]==char
- OS_STREQ_NONNULL = 11 # s1 == s2 (assert s1!=NULL,s2!=NULL)
- OS_STREQ_NONNULL_CHAR = 12 # s1 == char (assert s1!=NULL)
- OS_STREQ_CHECKNULL_CHAR = 13 # s1!=NULL and s1==char
- OS_STREQ_LENGTHOK = 14 # s1 == s2 (assert len(s1)==len(s2))
+ 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_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_offset_uni = OS_UNI_CONCAT - OS_STR_CONCAT
def __new__(cls, readonly_descrs_fields,
write_descrs_fields, write_descrs_arrays,
Modified: pypy/branch/jit-str-unicode/pypy/jit/codewriter/jtransform.py
==============================================================================
--- pypy/branch/jit-str-unicode/pypy/jit/codewriter/jtransform.py (original)
+++ pypy/branch/jit-str-unicode/pypy/jit/codewriter/jtransform.py Mon Oct 11 14:26:19 2010
@@ -316,6 +316,8 @@
prepare = self._handle_list_call
elif oopspec_name.startswith('stroruni.'):
prepare = self._handle_stroruni_call
+ elif oopspec_name == 'str.str2unicode':
+ prepare = self._handle_str2unicode_call
elif oopspec_name.startswith('virtual_ref'):
prepare = self._handle_virtual_ref_call
else:
@@ -1106,11 +1108,16 @@
[SoU, SoU],
lltype.Signed),
]:
+ if args[0].concretetype.TO == rstr.UNICODE:
+ otherindex += EffectInfo._OS_offset_uni
self._register_extra_helper(otherindex, othername,
argtypes, resulttype)
#
return self._handle_oopspec_call(op, args, dict[oopspec_name])
+ def _handle_str2unicode_call(self, op, oopspec_name, args):
+ return self._handle_oopspec_call(op, args, EffectInfo.OS_STR2UNICODE)
+
# ----------
# VirtualRefs.
Modified: pypy/branch/jit-str-unicode/pypy/jit/codewriter/test/test_jtransform.py
==============================================================================
--- pypy/branch/jit-str-unicode/pypy/jit/codewriter/test/test_jtransform.py (original)
+++ pypy/branch/jit-str-unicode/pypy/jit/codewriter/test/test_jtransform.py Mon Oct 11 14:26:19 2010
@@ -77,7 +77,8 @@
class FakeBuiltinCallControl:
def guess_call_kind(self, op):
return 'builtin'
- def getcalldescr(self, op, oopspecindex):
+ def getcalldescr(self, op, oopspecindex=None):
+ assert oopspecindex is not None # in this test
return 'calldescr-%d' % oopspecindex
def calldescr_canraise(self, calldescr):
return False
@@ -766,6 +767,24 @@
assert op1.args[3] == ListOfKind('ref', [v1])
assert op1.result == v4
+def test_str2unicode():
+ # test that the oopspec is present and correctly transformed
+ PSTR = lltype.Ptr(rstr.STR)
+ PUNICODE = lltype.Ptr(rstr.UNICODE)
+ FUNC = lltype.FuncType([PSTR], PUNICODE)
+ func = lltype.functionptr(FUNC, 'll_str2unicode',
+ _callable=rstr.LLHelpers.ll_str2unicode)
+ v1 = varoftype(PSTR)
+ v2 = varoftype(PUNICODE)
+ 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 op1.args[0].value == func
+ assert op1.args[1] == 'calldescr-%d' % effectinfo.EffectInfo.OS_STR2UNICODE
+ assert op1.args[2] == ListOfKind('ref', [v1])
+ assert op1.result == v2
+
def test_list_ll_arraycopy():
from pypy.rlib.rgc import ll_arraycopy
LIST = lltype.GcArray(lltype.Signed)
Modified: pypy/branch/jit-str-unicode/pypy/jit/metainterp/history.py
==============================================================================
--- pypy/branch/jit-str-unicode/pypy/jit/metainterp/history.py (original)
+++ pypy/branch/jit-str-unicode/pypy/jit/metainterp/history.py Mon Oct 11 14:26:19 2010
@@ -698,6 +698,21 @@
return result
_const_ptr_for_string = {}
+def get_const_ptr_for_unicode(s):
+ from pypy.rpython.annlowlevel import llunicode
+ if not we_are_translated():
+ try:
+ return _const_ptr_for_unicode[s]
+ except KeyError:
+ pass
+ if isinstance(s, str):
+ s = unicode(s)
+ result = ConstPtr(lltype.cast_opaque_ptr(llmemory.GCREF, llunicode(s)))
+ if not we_are_translated():
+ _const_ptr_for_unicode[s] = result
+ return result
+_const_ptr_for_unicode = {}
+
# ____________________________________________________________
# The TreeLoop class contains a loop or a generalized loop, i.e. a tree
Modified: pypy/branch/jit-str-unicode/pypy/jit/metainterp/optimizeopt/intbounds.py
==============================================================================
--- pypy/branch/jit-str-unicode/pypy/jit/metainterp/optimizeopt/intbounds.py (original)
+++ pypy/branch/jit-str-unicode/pypy/jit/metainterp/optimizeopt/intbounds.py Mon Oct 11 14:26:19 2010
@@ -191,6 +191,7 @@
v1.intbound.make_ge(IntLowerBound(0))
optimize_STRLEN = optimize_ARRAYLEN_GC
+ optimize_UNICODELEN = optimize_ARRAYLEN_GC
def make_int_lt(self, box1, box2):
v1 = self.getvalue(box1)
Modified: pypy/branch/jit-str-unicode/pypy/jit/metainterp/optimizeopt/rewrite.py
==============================================================================
--- pypy/branch/jit-str-unicode/pypy/jit/metainterp/optimizeopt/rewrite.py (original)
+++ pypy/branch/jit-str-unicode/pypy/jit/metainterp/optimizeopt/rewrite.py Mon Oct 11 14:26:19 2010
@@ -3,6 +3,7 @@
from pypy.jit.metainterp.history import ConstInt
from pypy.jit.metainterp.optimizeutil import _findall
from pypy.jit.metainterp.resoperation import rop, ResOperation
+from pypy.jit.codewriter.effectinfo import EffectInfo
class OptRewrite(Optimization):
"""Rewrite operations into equivalent, cheaper operations.
@@ -326,8 +327,37 @@
## return
## self.emit_operation(op)
-optimize_ops = _findall(OptRewrite, 'optimize_')
-
+ def optimize_CALL(self, op):
+ # dispatch based on 'oopspecindex' to a method that handles
+ # specifically the given oopspec call. For non-oopspec calls,
+ # oopspecindex is just zero.
+ effectinfo = op.getdescr().get_extra_info()
+ if effectinfo is not None:
+ oopspecindex = effectinfo.oopspecindex
+ if oopspecindex == EffectInfo.OS_ARRAYCOPY:
+ if self._optimize_CALL_ARRAYCOPY(op):
+ return
+ self.emit_operation(op)
+ def _optimize_CALL_ARRAYCOPY(self, op):
+ source_value = self.getvalue(op.getarg(1))
+ dest_value = self.getvalue(op.getarg(2))
+ source_start_box = self.get_constant_box(op.getarg(3))
+ dest_start_box = self.get_constant_box(op.getarg(4))
+ length = self.get_constant_box(op.getarg(5))
+ if (source_value.is_virtual() and source_start_box and dest_start_box
+ and length and dest_value.is_virtual()):
+ # XXX optimize the case where dest value is not virtual,
+ # but we still can avoid a mess
+ source_start = source_start_box.getint()
+ dest_start = dest_start_box.getint()
+ for index in range(length.getint()):
+ val = source_value.getitem(index + source_start)
+ dest_value.setitem(index + dest_start, val)
+ return True
+ if length and length.getint() == 0:
+ return True # 0-length arraycopy
+ return False
+
+optimize_ops = _findall(OptRewrite, 'optimize_')
-
Modified: pypy/branch/jit-str-unicode/pypy/jit/metainterp/optimizeopt/string.py
==============================================================================
--- pypy/branch/jit-str-unicode/pypy/jit/metainterp/optimizeopt/string.py (original)
+++ pypy/branch/jit-str-unicode/pypy/jit/metainterp/optimizeopt/string.py Mon Oct 11 14:26:19 2010
@@ -3,6 +3,7 @@
from pypy.jit.metainterp.history import Box, BoxInt, BoxPtr
from pypy.jit.metainterp.history import Const, ConstInt, ConstPtr
from pypy.jit.metainterp.history import get_const_ptr_for_string
+from pypy.jit.metainterp.history import get_const_ptr_for_unicode
from pypy.jit.metainterp.resoperation import rop, ResOperation
from pypy.jit.metainterp.optimizeopt import optimizer, virtualize
from pypy.jit.metainterp.optimizeopt.optimizer import CONST_0, CONST_1
@@ -11,56 +12,103 @@
from pypy.jit.codewriter.effectinfo import EffectInfo, callinfo_for_oopspec
from pypy.jit.codewriter import heaptracker
from pypy.rlib.unroll import unrolling_iterable
+from pypy.rlib.objectmodel import specialize
+
+
+class StrOrUnicode(object):
+ def __init__(self, LLTYPE, hlstr, emptystr, chr,
+ NEWSTR, STRLEN, STRGETITEM, STRSETITEM, COPYSTRCONTENT,
+ OS_offset):
+ self.LLTYPE = LLTYPE
+ self.hlstr = hlstr
+ self.emptystr = emptystr
+ self.chr = chr
+ self.NEWSTR = NEWSTR
+ self.STRLEN = STRLEN
+ self.STRGETITEM = STRGETITEM
+ self.STRSETITEM = STRSETITEM
+ self.COPYSTRCONTENT = COPYSTRCONTENT
+ self.OS_offset = OS_offset
+
+ def _freeze_(self):
+ return True
+
+mode_string = StrOrUnicode(rstr.STR, annlowlevel.hlstr, '', chr,
+ rop.NEWSTR, rop.STRLEN, rop.STRGETITEM,
+ rop.STRSETITEM, rop.COPYSTRCONTENT, 0)
+mode_unicode = StrOrUnicode(rstr.UNICODE, annlowlevel.hlunicode, u'', unichr,
+ rop.NEWUNICODE, rop.UNICODELEN, rop.UNICODEGETITEM,
+ rop.UNICODESETITEM, rop.COPYUNICODECONTENT,
+ EffectInfo._OS_offset_uni)
+
+# ____________________________________________________________
class __extend__(optimizer.OptValue):
"""New methods added to the base class OptValue for this file."""
- def getstrlen(self, newoperations):
- s = self.get_constant_string()
- if s is not None:
- return ConstInt(len(s))
+ def getstrlen(self, newoperations, mode):
+ if mode is mode_string:
+ s = self.get_constant_string_spec(mode_string)
+ if s is not None:
+ return ConstInt(len(s))
else:
- if newoperations is None:
- return None
- self.ensure_nonnull()
- box = self.force_box()
- lengthbox = BoxInt()
- newoperations.append(ResOperation(rop.STRLEN, [box], lengthbox))
- return lengthbox
+ s = self.get_constant_string_spec(mode_unicode)
+ if s is not None:
+ return ConstInt(len(s))
+ if newoperations is None:
+ return None
+ self.ensure_nonnull()
+ box = self.force_box()
+ lengthbox = BoxInt()
+ newoperations.append(ResOperation(mode.STRLEN, [box], lengthbox))
+ return lengthbox
- def get_constant_string(self):
+ @specialize.arg(1)
+ def get_constant_string_spec(self, mode):
if self.is_constant():
- s = self.box.getref(lltype.Ptr(rstr.STR))
- return annlowlevel.hlstr(s)
+ s = self.box.getref(lltype.Ptr(mode.LLTYPE))
+ return mode.hlstr(s)
else:
return None
- def string_copy_parts(self, newoperations, targetbox, offsetbox):
+ def string_copy_parts(self, newoperations, targetbox, offsetbox, mode):
# Copies the pointer-to-string 'self' into the target string
# given by 'targetbox', at the specified offset. Returns the offset
# at the end of the copy.
- lengthbox = self.getstrlen(newoperations)
+ lengthbox = self.getstrlen(newoperations, mode)
srcbox = self.force_box()
return copy_str_content(newoperations, srcbox, targetbox,
- CONST_0, offsetbox, lengthbox)
+ CONST_0, offsetbox, lengthbox, mode)
class VAbstractStringValue(virtualize.AbstractVirtualValue):
- _attrs_ = ()
+ _attrs_ = ('mode',)
+
+ def __init__(self, optimizer, keybox, source_op, mode):
+ virtualize.AbstractVirtualValue.__init__(self, optimizer, keybox,
+ source_op)
+ self.mode = mode
def _really_force(self):
- s = self.get_constant_string()
- if s is not None:
- c_s = get_const_ptr_for_string(s)
- self.make_constant(c_s)
- return
+ if self.mode is mode_string:
+ s = self.get_constant_string_spec(mode_string)
+ if s is not None:
+ c_s = get_const_ptr_for_string(s)
+ self.make_constant(c_s)
+ return
+ else:
+ s = self.get_constant_string_spec(mode_unicode)
+ if s is not None:
+ c_s = get_const_ptr_for_unicode(s)
+ self.make_constant(c_s)
+ return
assert self.source_op is not None
self.box = box = self.source_op.result
newoperations = self.optimizer.newoperations
- lengthbox = self.getstrlen(newoperations)
- newoperations.append(ResOperation(rop.NEWSTR, [lengthbox], box))
- self.string_copy_parts(newoperations, box, CONST_0)
+ lengthbox = self.getstrlen(newoperations, self.mode)
+ newoperations.append(ResOperation(self.mode.NEWSTR, [lengthbox], box))
+ self.string_copy_parts(newoperations, box, CONST_0, self.mode)
class VStringPlainValue(VAbstractStringValue):
@@ -74,7 +122,7 @@
assert 0 <= start <= stop <= len(longerlist)
self._chars = longerlist[start:stop]
- def getstrlen(self, _):
+ def getstrlen(self, _, mode):
if self._lengthbox is None:
self._lengthbox = ConstInt(len(self._chars))
return self._lengthbox
@@ -86,18 +134,21 @@
assert isinstance(charvalue, optimizer.OptValue)
self._chars[index] = charvalue
- def get_constant_string(self):
+ @specialize.arg(1)
+ def get_constant_string_spec(self, mode):
for c in self._chars:
if c is optimizer.CVAL_UNINITIALIZED_ZERO or not c.is_constant():
return None
- return ''.join([chr(c.box.getint()) for c in self._chars])
+ return mode.emptystr.join([mode.chr(c.box.getint())
+ for c in self._chars])
- def string_copy_parts(self, newoperations, targetbox, offsetbox):
+ def string_copy_parts(self, newoperations, targetbox, offsetbox, mode):
for i in range(len(self._chars)):
charbox = self._chars[i].force_box()
- newoperations.append(ResOperation(rop.STRSETITEM, [targetbox,
- offsetbox,
- charbox], None))
+ newoperations.append(ResOperation(mode.STRSETITEM, [targetbox,
+ offsetbox,
+ charbox],
+ None))
offsetbox = _int_add(newoperations, offsetbox, CONST_1)
return offsetbox
@@ -109,7 +160,7 @@
value.get_args_for_fail(modifier)
def _make_virtual(self, modifier):
- return modifier.make_vstrplain()
+ return modifier.make_vstrplain(self.mode is mode_unicode)
class VStringConcatValue(VAbstractStringValue):
@@ -120,23 +171,24 @@
self.right = right
self.lengthbox = lengthbox
- def getstrlen(self, _):
+ def getstrlen(self, _, mode):
return self.lengthbox
- def get_constant_string(self):
- s1 = self.left.get_constant_string()
+ @specialize.arg(1)
+ def get_constant_string_spec(self, mode):
+ s1 = self.left.get_constant_string_spec(mode)
if s1 is None:
return None
- s2 = self.right.get_constant_string()
+ s2 = self.right.get_constant_string_spec(mode)
if s2 is None:
return None
return s1 + s2
- def string_copy_parts(self, newoperations, targetbox, offsetbox):
+ def string_copy_parts(self, newoperations, targetbox, offsetbox, mode):
offsetbox = self.left.string_copy_parts(newoperations, targetbox,
- offsetbox)
+ offsetbox, mode)
offsetbox = self.right.string_copy_parts(newoperations, targetbox,
- offsetbox)
+ offsetbox, mode)
return offsetbox
def get_args_for_fail(self, modifier):
@@ -150,7 +202,7 @@
self.right.get_args_for_fail(modifier)
def _make_virtual(self, modifier):
- return modifier.make_vstrconcat()
+ return modifier.make_vstrconcat(self.mode is mode_unicode)
class VStringSliceValue(VAbstractStringValue):
@@ -162,12 +214,13 @@
self.vstart = vstart
self.vlength = vlength
- def getstrlen(self, _):
+ def getstrlen(self, _, mode):
return self.vlength.force_box()
- def get_constant_string(self):
+ @specialize.arg(1)
+ def get_constant_string_spec(self, mode):
if self.vstart.is_constant() and self.vlength.is_constant():
- s1 = self.vstr.get_constant_string()
+ s1 = self.vstr.get_constant_string_spec(mode)
if s1 is None:
return None
start = self.vstart.box.getint()
@@ -177,12 +230,12 @@
return s1[start : start + length]
return None
- def string_copy_parts(self, newoperations, targetbox, offsetbox):
- lengthbox = self.getstrlen(newoperations)
+ def string_copy_parts(self, newoperations, targetbox, offsetbox, mode):
+ lengthbox = self.getstrlen(newoperations, mode)
return copy_str_content(newoperations,
self.vstr.force_box(), targetbox,
self.vstart.force_box(), offsetbox,
- lengthbox)
+ lengthbox, mode)
def get_args_for_fail(self, modifier):
if self.box is None and not modifier.already_seen_virtual(self.keybox):
@@ -195,11 +248,11 @@
self.vlength.get_args_for_fail(modifier)
def _make_virtual(self, modifier):
- return modifier.make_vstrslice()
+ return modifier.make_vstrslice(self.mode is mode_unicode)
def copy_str_content(newoperations, srcbox, targetbox,
- srcoffsetbox, offsetbox, lengthbox):
+ srcoffsetbox, offsetbox, lengthbox, mode):
if isinstance(srcbox, ConstPtr) and isinstance(srcoffsetbox, Const):
M = 5
else:
@@ -208,17 +261,18 @@
# up to M characters are done "inline", i.e. with STRGETITEM/STRSETITEM
# instead of just a COPYSTRCONTENT.
for i in range(lengthbox.value):
- charbox = _strgetitem(newoperations, srcbox, srcoffsetbox)
+ charbox = _strgetitem(newoperations, srcbox, srcoffsetbox, mode)
srcoffsetbox = _int_add(newoperations, srcoffsetbox, CONST_1)
- newoperations.append(ResOperation(rop.STRSETITEM, [targetbox,
- offsetbox,
- charbox], None))
+ newoperations.append(ResOperation(mode.STRSETITEM, [targetbox,
+ offsetbox,
+ charbox],
+ None))
offsetbox = _int_add(newoperations, offsetbox, CONST_1)
else:
nextoffsetbox = _int_add(newoperations, offsetbox, lengthbox)
- op = ResOperation(rop.COPYSTRCONTENT, [srcbox, targetbox,
- srcoffsetbox, offsetbox,
- lengthbox], None)
+ op = ResOperation(mode.COPYSTRCONTENT, [srcbox, targetbox,
+ srcoffsetbox, offsetbox,
+ lengthbox], None)
newoperations.append(op)
offsetbox = nextoffsetbox
return offsetbox
@@ -245,12 +299,16 @@
newoperations.append(ResOperation(rop.INT_SUB, [box1, box2], resbox))
return resbox
-def _strgetitem(newoperations, strbox, indexbox):
+def _strgetitem(newoperations, strbox, indexbox, mode):
if isinstance(strbox, ConstPtr) and isinstance(indexbox, ConstInt):
- s = strbox.getref(lltype.Ptr(rstr.STR))
- return ConstInt(ord(s.chars[indexbox.getint()]))
+ if mode is mode_string:
+ s = strbox.getref(lltype.Ptr(rstr.STR))
+ return ConstInt(ord(s.chars[indexbox.getint()]))
+ else:
+ s = strbox.getref(lltype.Ptr(rstr.UNICODE))
+ return ConstInt(ord(s.chars[indexbox.getint()]))
resbox = BoxInt()
- newoperations.append(ResOperation(rop.STRGETITEM, [strbox, indexbox],
+ newoperations.append(ResOperation(mode.STRGETITEM, [strbox, indexbox],
resbox))
return resbox
@@ -258,62 +316,34 @@
class OptString(optimizer.Optimization):
"Handling of strings and unicodes."
- def make_vstring_plain(self, box, source_op=None):
- vvalue = VStringPlainValue(self.optimizer, box, source_op)
+ def make_vstring_plain(self, box, source_op, mode):
+ vvalue = VStringPlainValue(self.optimizer, box, source_op, mode)
self.make_equal_to(box, vvalue)
return vvalue
- def make_vstring_concat(self, box, source_op=None):
- vvalue = VStringConcatValue(self.optimizer, box, source_op)
+ def make_vstring_concat(self, box, source_op, mode):
+ vvalue = VStringConcatValue(self.optimizer, box, source_op, mode)
self.make_equal_to(box, vvalue)
return vvalue
- def make_vstring_slice(self, box, source_op=None):
- vvalue = VStringSliceValue(self.optimizer, box, source_op)
+ def make_vstring_slice(self, box, source_op, mode):
+ vvalue = VStringSliceValue(self.optimizer, box, source_op, mode)
self.make_equal_to(box, vvalue)
return vvalue
- def optimize_CALL(self, op):
- # dispatch based on 'oopspecindex' to a method that handles
- # specifically the given oopspec call. For non-oopspec calls,
- # oopspecindex is just zero.
- effectinfo = op.getdescr().get_extra_info()
- if effectinfo is not None:
- oopspecindex = effectinfo.oopspecindex
- for value, meth in opt_call_oopspec_ops:
- if oopspecindex == value:
- if meth(self, op):
- return
- self.emit_operation(op)
-
- def opt_call_oopspec_ARRAYCOPY(self, op):
- source_value = self.getvalue(op.getarg(1))
- dest_value = self.getvalue(op.getarg(2))
- source_start_box = self.get_constant_box(op.getarg(3))
- dest_start_box = self.get_constant_box(op.getarg(4))
- length = self.get_constant_box(op.getarg(5))
- if (source_value.is_virtual() and source_start_box and dest_start_box
- and length and dest_value.is_virtual()):
- # XXX optimize the case where dest value is not virtual,
- # but we still can avoid a mess
- source_start = source_start_box.getint()
- dest_start = dest_start_box.getint()
- for index in range(length.getint()):
- val = source_value.getitem(index + source_start)
- dest_value.setitem(index + dest_start, val)
- return True
- if length and length.getint() == 0:
- return True # 0-length arraycopy
- return False
-
def optimize_NEWSTR(self, op):
+ self._optimize_NEWSTR(op, mode_string)
+ def optimize_NEWUNICODE(self, op):
+ self._optimize_NEWSTR(op, mode_unicode)
+
+ def _optimize_NEWSTR(self, op, mode):
length_box = self.get_constant_box(op.getarg(0))
if length_box:
# if the original 'op' did not have a ConstInt as argument,
# build a new one with the ConstInt argument
if not isinstance(op.getarg(0), ConstInt):
- op = ResOperation(rop.NEWSTR, [length_box], op.result)
- vvalue = self.make_vstring_plain(op.result, op)
+ op = ResOperation(mode.NEWSTR, [length_box], op.result)
+ vvalue = self.make_vstring_plain(op.result, op, mode)
vvalue.setup(length_box.getint())
else:
self.getvalue(op.result).ensure_nonnull()
@@ -329,13 +359,20 @@
value.ensure_nonnull()
self.emit_operation(op)
+ optimize_UNICODESETITEM = optimize_STRSETITEM
+
def optimize_STRGETITEM(self, op):
+ self._optimize_STRGETITEM(op, mode_string)
+ def optimize_UNICODEGETITEM(self, op):
+ self._optimize_STRGETITEM(op, mode_unicode)
+
+ def _optimize_STRGETITEM(self, op, mode):
value = self.getvalue(op.getarg(0))
vindex = self.getvalue(op.getarg(1))
- vresult = self.strgetitem(value, vindex)
+ vresult = self.strgetitem(value, vindex, mode)
self.make_equal_to(op.result, vresult)
- def strgetitem(self, value, vindex):
+ def strgetitem(self, value, vindex, mode):
value.ensure_nonnull()
#
if value.is_virtual() and isinstance(value, VStringSliceValue):
@@ -350,28 +387,71 @@
return value.getitem(vindex.box.getint())
#
resbox = _strgetitem(self.optimizer.newoperations,
- value.force_box(),vindex.force_box())
+ value.force_box(),vindex.force_box(), mode)
return self.getvalue(resbox)
def optimize_STRLEN(self, op):
+ self._optimize_STRLEN(op, mode_string)
+ def optimize_UNICODELEN(self, op):
+ self._optimize_STRLEN(op, mode_unicode)
+
+ def _optimize_STRLEN(self, op, mode):
value = self.getvalue(op.getarg(0))
- lengthbox = value.getstrlen(self.optimizer.newoperations)
+ lengthbox = value.getstrlen(self.optimizer.newoperations, mode)
self.make_equal_to(op.result, self.getvalue(lengthbox))
- def opt_call_oopspec_STR_CONCAT(self, op):
+ def optimize_CALL(self, op):
+ # dispatch based on 'oopspecindex' to a method that handles
+ # specifically the given oopspec call. For non-oopspec calls,
+ # oopspecindex is just zero.
+ effectinfo = op.getdescr().get_extra_info()
+ if effectinfo is not None:
+ oopspecindex = effectinfo.oopspecindex
+ for value, meth in opt_call_oopspec_ops:
+ if oopspecindex == value: # a match with the OS_STR_xxx
+ if meth(self, op, mode_string):
+ return
+ break
+ if oopspecindex == value + EffectInfo._OS_offset_uni:
+ # a match with the OS_UNI_xxx
+ if meth(self, op, mode_unicode):
+ return
+ break
+ if oopspecindex == EffectInfo.OS_STR2UNICODE:
+ if self.opt_call_str_STR2UNICODE(op):
+ return
+ self.emit_operation(op)
+
+ def opt_call_str_STR2UNICODE(self, op):
+ # Constant-fold unicode("constant string").
+ # More generally, supporting non-constant but virtual cases is
+ # not obvious, because of the exception UnicodeDecodeError that
+ # can be raised by ll_str2unicode()
+ varg = self.getvalue(op.getarg(1))
+ s = varg.get_constant_string_spec(mode_string)
+ if s is None:
+ return False
+ try:
+ u = unicode(s)
+ except UnicodeDecodeError:
+ return False
+ self.make_constant(op.result, get_const_ptr_for_unicode(u))
+ return True
+
+ def opt_call_stroruni_STR_CONCAT(self, op, mode):
vleft = self.getvalue(op.getarg(1))
vright = self.getvalue(op.getarg(2))
vleft.ensure_nonnull()
vright.ensure_nonnull()
newoperations = self.optimizer.newoperations
- len1box = vleft.getstrlen(newoperations)
- len2box = vright.getstrlen(newoperations)
+ len1box = vleft.getstrlen(newoperations, mode)
+ len2box = vright.getstrlen(newoperations, mode)
lengthbox = _int_add(newoperations, len1box, len2box)
- value = self.make_vstring_concat(op.result, op)
+ value = self.make_vstring_concat(op.result, op, mode)
value.setup(vleft, vright, lengthbox)
return True
- def opt_call_oopspec_STR_SLICE(self, op):
+ def opt_call_stroruni_STR_SLICE(self, op, mode):
newoperations = self.optimizer.newoperations
vstr = self.getvalue(op.getarg(1))
vstart = self.getvalue(op.getarg(2))
@@ -380,7 +460,7 @@
if (isinstance(vstr, VStringPlainValue) and vstart.is_constant()
and vstop.is_constant()):
# slicing with constant bounds of a VStringPlainValue
- value = self.make_vstring_plain(op.result, op)
+ value = self.make_vstring_plain(op.result, op, mode)
value.setup_slice(vstr._chars, vstart.box.getint(),
vstop.box.getint())
return True
@@ -398,16 +478,16 @@
vstart.force_box())
vstart = self.getvalue(startbox)
#
- value = self.make_vstring_slice(op.result, op)
+ value = self.make_vstring_slice(op.result, op, mode)
value.setup(vstr, vstart, self.getvalue(lengthbox))
return True
- def opt_call_oopspec_STR_EQUAL(self, op):
+ def opt_call_stroruni_STR_EQUAL(self, op, mode):
v1 = self.getvalue(op.getarg(1))
v2 = self.getvalue(op.getarg(2))
#
- l1box = v1.getstrlen(None)
- l2box = v2.getstrlen(None)
+ l1box = v1.getstrlen(None, mode)
+ l2box = v2.getstrlen(None, mode)
if (l1box is not None and l2box is not None and
isinstance(l1box, ConstInt) and
isinstance(l2box, ConstInt) and
@@ -416,13 +496,13 @@
self.make_constant(op.result, CONST_0)
return True
#
- if self.handle_str_equal_level1(v1, v2, op.result):
+ if self.handle_str_equal_level1(v1, v2, op.result, mode):
return True
- if self.handle_str_equal_level1(v2, v1, op.result):
+ if self.handle_str_equal_level1(v2, v1, op.result, mode):
return True
- if self.handle_str_equal_level2(v1, v2, op.result):
+ if self.handle_str_equal_level2(v1, v2, op.result, mode):
return True
- if self.handle_str_equal_level2(v2, v1, op.result):
+ if self.handle_str_equal_level2(v2, v1, op.result, mode):
return True
#
if v1.is_nonnull() and v2.is_nonnull():
@@ -434,37 +514,37 @@
else:
do = EffectInfo.OS_STREQ_NONNULL
self.generate_modified_call(do, [v1.force_box(),
- v2.force_box()], op.result)
+ v2.force_box()], op.result, mode)
return True
return False
- def handle_str_equal_level1(self, v1, v2, resultbox):
- l2box = v2.getstrlen(None)
+ def handle_str_equal_level1(self, v1, v2, resultbox, mode):
+ l2box = v2.getstrlen(None, mode)
if isinstance(l2box, ConstInt):
if l2box.value == 0:
- lengthbox = v1.getstrlen(self.optimizer.newoperations)
+ lengthbox = v1.getstrlen(self.optimizer.newoperations, mode)
seo = self.optimizer.send_extra_operation
seo(ResOperation(rop.INT_EQ, [lengthbox, CONST_0], resultbox))
return True
if l2box.value == 1:
- l1box = v1.getstrlen(None)
+ l1box = v1.getstrlen(None, mode)
if isinstance(l1box, ConstInt) and l1box.value == 1:
# comparing two single chars
- vchar1 = self.strgetitem(v1, optimizer.CVAL_ZERO)
- vchar2 = self.strgetitem(v2, optimizer.CVAL_ZERO)
+ vchar1 = self.strgetitem(v1, optimizer.CVAL_ZERO, mode)
+ vchar2 = self.strgetitem(v2, optimizer.CVAL_ZERO, mode)
seo = self.optimizer.send_extra_operation
seo(ResOperation(rop.INT_EQ, [vchar1.force_box(),
vchar2.force_box()],
resultbox))
return True
if isinstance(v1, VStringSliceValue):
- vchar = self.strgetitem(v2, optimizer.CVAL_ZERO)
+ vchar = self.strgetitem(v2, optimizer.CVAL_ZERO, mode)
do = EffectInfo.OS_STREQ_SLICE_CHAR
self.generate_modified_call(do, [v1.vstr.force_box(),
v1.vstart.force_box(),
v1.vlength.force_box(),
vchar.force_box()],
- resultbox)
+ resultbox, mode)
return True
#
if v2.is_null():
@@ -482,17 +562,18 @@
#
return False
- def handle_str_equal_level2(self, v1, v2, resultbox):
- l2box = v2.getstrlen(None)
+ def handle_str_equal_level2(self, v1, v2, resultbox, mode):
+ l2box = v2.getstrlen(None, mode)
if isinstance(l2box, ConstInt):
if l2box.value == 1:
- vchar = self.strgetitem(v2, optimizer.CVAL_ZERO)
+ vchar = self.strgetitem(v2, optimizer.CVAL_ZERO, mode)
if v1.is_nonnull():
do = EffectInfo.OS_STREQ_NONNULL_CHAR
else:
do = EffectInfo.OS_STREQ_CHECKNULL_CHAR
self.generate_modified_call(do, [v1.force_box(),
- vchar.force_box()], resultbox)
+ vchar.force_box()], resultbox,
+ mode)
return True
#
if v1.is_virtual() and isinstance(v1, VStringSliceValue):
@@ -503,11 +584,12 @@
self.generate_modified_call(do, [v1.vstr.force_box(),
v1.vstart.force_box(),
v1.vlength.force_box(),
- v2.force_box()], resultbox)
+ v2.force_box()], resultbox, mode)
return True
return False
- def generate_modified_call(self, oopspecindex, args, result):
+ def generate_modified_call(self, oopspecindex, args, result, mode):
+ oopspecindex += mode.OS_offset
calldescr, func = callinfo_for_oopspec(oopspecindex)
op = ResOperation(rop.CALL, [ConstInt(func)] + args, result,
descr=calldescr)
@@ -525,7 +607,7 @@
optimize_ops = _findall(OptString, 'optimize_')
def _findall_call_oopspec():
- prefix = 'opt_call_oopspec_'
+ prefix = 'opt_call_stroruni_'
result = []
for name in dir(OptString):
if name.startswith(prefix):
Modified: pypy/branch/jit-str-unicode/pypy/jit/metainterp/resume.py
==============================================================================
--- pypy/branch/jit-str-unicode/pypy/jit/metainterp/resume.py (original)
+++ pypy/branch/jit-str-unicode/pypy/jit/metainterp/resume.py Mon Oct 11 14:26:19 2010
@@ -255,13 +255,19 @@
def make_varray(self, arraydescr):
return VArrayInfo(arraydescr)
- def make_vstrplain(self):
+ def make_vstrplain(self, is_unicode=False):
+ if is_unicode:
+ return VUniPlainInfo()
return VStrPlainInfo()
- def make_vstrconcat(self):
+ def make_vstrconcat(self, is_unicode=False):
+ if is_unicode:
+ return VUniConcatInfo()
return VStrConcatInfo()
- def make_vstrslice(self):
+ def make_vstrslice(self, is_unicode=False):
+ if is_unicode:
+ return VUniSliceInfo()
return VStrSliceInfo()
def register_virtual_fields(self, virtualbox, fieldboxes):
@@ -550,6 +556,60 @@
for i in self.fieldnums:
debug_print("\t\t", str(untag(i)))
+
+class VUniPlainInfo(AbstractVirtualInfo):
+ """Stands for the unicode string made out of the characters of all
+ fieldnums."""
+
+ @specialize.argtype(1)
+ def allocate(self, decoder, index):
+ length = len(self.fieldnums)
+ string = decoder.allocate_unicode(length)
+ decoder.virtuals_cache[index] = string
+ for i in range(length):
+ decoder.unicode_setitem(string, i, self.fieldnums[i])
+ return string
+
+ def debug_prints(self):
+ debug_print("\tvuniplaininfo length", len(self.fieldnums))
+
+
+class VUniConcatInfo(AbstractVirtualInfo):
+ """Stands for the unicode string made out of the concatenation of two
+ other unicode strings."""
+
+ @specialize.argtype(1)
+ def allocate(self, decoder, index):
+ # xxx for blackhole resuming, this will build all intermediate
+ # strings and throw them away immediately, which is a bit sub-
+ # efficient. Not sure we care.
+ left, right = self.fieldnums
+ string = decoder.concat_unicodes(left, right)
+ decoder.virtuals_cache[index] = string
+ return string
+
+ def debug_prints(self):
+ debug_print("\tvuniconcatinfo")
+ for i in self.fieldnums:
+ debug_print("\t\t", str(untag(i)))
+
+
+class VUniSliceInfo(AbstractVirtualInfo):
+ """Stands for the unicode string made out of slicing another
+ unicode string."""
+
+ @specialize.argtype(1)
+ def allocate(self, decoder, index):
+ largerstr, start, length = self.fieldnums
+ string = decoder.slice_unicode(largerstr, start, length)
+ decoder.virtuals_cache[index] = string
+ return string
+
+ def debug_prints(self):
+ debug_print("\tvunisliceinfo")
+ for i in self.fieldnums:
+ debug_print("\t\t", str(untag(i)))
+
# ____________________________________________________________
class AbstractResumeDataReader(object):
@@ -725,6 +785,32 @@
return self.metainterp.execute_and_record_varargs(
rop.CALL, [ConstInt(func), strbox, startbox, stopbox], calldescr)
+ def allocate_unicode(self, length):
+ return self.metainterp.execute_and_record(rop.NEWUNICODE,
+ None, ConstInt(length))
+
+ def unicode_setitem(self, strbox, index, charnum):
+ charbox = self.decode_box(charnum, INT)
+ self.metainterp.execute_and_record(rop.UNICODESETITEM, None,
+ strbox, ConstInt(index), charbox)
+
+ def concat_unicodes(self, str1num, str2num):
+ calldescr, func = callinfo_for_oopspec(EffectInfo.OS_UNI_CONCAT)
+ str1box = self.decode_box(str1num, REF)
+ str2box = self.decode_box(str2num, REF)
+ return self.metainterp.execute_and_record_varargs(
+ rop.CALL, [ConstInt(func), str1box, str2box], calldescr)
+
+ def slice_unicode(self, strnum, startnum, lengthnum):
+ calldescr, func = callinfo_for_oopspec(EffectInfo.OS_UNI_SLICE)
+ strbox = self.decode_box(strnum, REF)
+ startbox = self.decode_box(startnum, INT)
+ lengthbox = self.decode_box(lengthnum, INT)
+ stopbox = self.metainterp.execute_and_record(rop.INT_ADD, None,
+ startbox, lengthbox)
+ return self.metainterp.execute_and_record_varargs(
+ rop.CALL, [ConstInt(func), strbox, startbox, stopbox], calldescr)
+
def setfield(self, descr, structbox, fieldnum):
if descr.is_pointer_field():
kind = REF
@@ -967,6 +1053,31 @@
result = funcptr(str, start, start + length)
return lltype.cast_opaque_ptr(llmemory.GCREF, result)
+ def allocate_unicode(self, length):
+ return self.cpu.bh_newunicode(length)
+
+ def unicode_setitem(self, str, index, charnum):
+ char = self.decode_int(charnum)
+ self.cpu.bh_unicodesetitem(str, index, char)
+
+ def concat_unicodes(self, str1num, str2num):
+ str1 = self.decode_ref(str1num)
+ str2 = self.decode_ref(str2num)
+ str1 = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), str1)
+ str2 = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), str2)
+ funcptr = funcptr_for_oopspec(EffectInfo.OS_UNI_CONCAT)
+ result = funcptr(str1, str2)
+ return lltype.cast_opaque_ptr(llmemory.GCREF, result)
+
+ def slice_unicode(self, strnum, startnum, lengthnum):
+ str = self.decode_ref(strnum)
+ start = self.decode_int(startnum)
+ length = self.decode_int(lengthnum)
+ str = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), str)
+ funcptr = funcptr_for_oopspec(EffectInfo.OS_UNI_SLICE)
+ result = funcptr(str, start, start + length)
+ return lltype.cast_opaque_ptr(llmemory.GCREF, result)
+
def setfield(self, descr, struct, fieldnum):
if descr.is_pointer_field():
newvalue = self.decode_ref(fieldnum)
Modified: pypy/branch/jit-str-unicode/pypy/jit/metainterp/test/oparser.py
==============================================================================
--- pypy/branch/jit-str-unicode/pypy/jit/metainterp/test/oparser.py (original)
+++ pypy/branch/jit-str-unicode/pypy/jit/metainterp/test/oparser.py Mon Oct 11 14:26:19 2010
@@ -5,7 +5,7 @@
from pypy.jit.metainterp.history import TreeLoop, BoxInt, ConstInt,\
ConstObj, ConstPtr, Box, BasicFailDescr, BoxFloat, ConstFloat,\
- LoopToken, get_const_ptr_for_string
+ LoopToken, get_const_ptr_for_string, get_const_ptr_for_unicode
from pypy.jit.metainterp.resoperation import rop, ResOperation, ResOpWithDescr, N_aryOp
from pypy.jit.metainterp.typesystem import llhelper
from pypy.jit.codewriter.heaptracker import adr2int
@@ -158,10 +158,15 @@
except ValueError:
if self.is_float(arg):
return ConstFloat(float(arg))
- if arg.startswith('"') or arg.startswith("'"):
+ if (arg.startswith('"') or arg.startswith("'") or
+ arg.startswith('s"')):
# XXX ootype
- info = arg.strip("'\"")
+ info = arg[1:].strip("'\"")
return get_const_ptr_for_string(info)
+ if arg.startswith('u"'):
+ # XXX ootype
+ info = arg[1:].strip("'\"")
+ return get_const_ptr_for_unicode(info)
if arg.startswith('ConstClass('):
name = arg[len('ConstClass('):-1]
return self.get_const(name, 'class')
Modified: pypy/branch/jit-str-unicode/pypy/jit/metainterp/test/test_optimizefindnode.py
==============================================================================
--- pypy/branch/jit-str-unicode/pypy/jit/metainterp/test/test_optimizefindnode.py (original)
+++ pypy/branch/jit-str-unicode/pypy/jit/metainterp/test/test_optimizefindnode.py Mon Oct 11 14:26:19 2010
@@ -117,33 +117,32 @@
EffectInfo.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE))
arraycopydescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
EffectInfo([], [], [], oopspecindex=EffectInfo.OS_ARRAYCOPY))
- strconcatdescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
- EffectInfo([], [], [], oopspecindex=EffectInfo.OS_STR_CONCAT))
- slicedescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
- EffectInfo([], [], [], oopspecindex=EffectInfo.OS_STR_SLICE))
- strequaldescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
- EffectInfo([], [], [], oopspecindex=EffectInfo.OS_STR_EQUAL))
- streq_slice_checknull_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
- EffectInfo([], [], [],
- oopspecindex=EffectInfo.OS_STREQ_SLICE_CHECKNULL))
- streq_slice_nonnull_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
- EffectInfo([], [], [],
- oopspecindex=EffectInfo.OS_STREQ_SLICE_NONNULL))
- streq_slice_char_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
- EffectInfo([], [], [],
- oopspecindex=EffectInfo.OS_STREQ_SLICE_CHAR))
- streq_nonnull_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
- EffectInfo([], [], [],
- oopspecindex=EffectInfo.OS_STREQ_NONNULL))
- streq_nonnull_char_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
- EffectInfo([], [], [],
- oopspecindex=EffectInfo.OS_STREQ_NONNULL_CHAR))
- streq_checknull_char_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
- EffectInfo([], [], [],
- oopspecindex=EffectInfo.OS_STREQ_CHECKNULL_CHAR))
- streq_lengthok_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
- EffectInfo([], [], [],
- oopspecindex=EffectInfo.OS_STREQ_LENGTHOK))
+
+ for _name, _os in [
+ ('strconcatdescr', 'OS_STR_CONCAT'),
+ ('strslicedescr', 'OS_STR_SLICE'),
+ ('strequaldescr', 'OS_STR_EQUAL'),
+ ('streq_slice_checknull_descr', 'OS_STREQ_SLICE_CHECKNULL'),
+ ('streq_slice_nonnull_descr', 'OS_STREQ_SLICE_NONNULL'),
+ ('streq_slice_char_descr', 'OS_STREQ_SLICE_CHAR'),
+ ('streq_nonnull_descr', 'OS_STREQ_NONNULL'),
+ ('streq_nonnull_char_descr', 'OS_STREQ_NONNULL_CHAR'),
+ ('streq_checknull_char_descr', 'OS_STREQ_CHECKNULL_CHAR'),
+ ('streq_lengthok_descr', 'OS_STREQ_LENGTHOK'),
+ ]:
+ _oopspecindex = getattr(EffectInfo, _os)
+ locals()[_name] = \
+ cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
+ EffectInfo([], [], [], oopspecindex=_oopspecindex))
+ #
+ _oopspecindex = getattr(EffectInfo, _os.replace('STR', 'UNI'))
+ locals()[_name.replace('str', 'unicode')] = \
+ cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
+ EffectInfo([], [], [], oopspecindex=_oopspecindex))
+
+ s2u_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
+ EffectInfo([], [], [], oopspecindex=EffectInfo.OS_STR2UNICODE))
+ #
class LoopToken(AbstractDescr):
pass
Modified: pypy/branch/jit-str-unicode/pypy/jit/metainterp/test/test_optimizeopt.py
==============================================================================
--- pypy/branch/jit-str-unicode/pypy/jit/metainterp/test/test_optimizeopt.py (original)
+++ pypy/branch/jit-str-unicode/pypy/jit/metainterp/test/test_optimizeopt.py Mon Oct 11 14:26:19 2010
@@ -3487,7 +3487,7 @@
i0 = strlen(p0)
jump(p0)
"""
- self.optimize_loop(ops, 'Not', expected)
+ self.optimize_strunicode_loop(ops, 'Not', expected)
def test_addsub_const(self):
ops = """
@@ -3893,6 +3893,15 @@
"""
self.optimize_loop(ops, 'Not, Not', expected)
+ # ----------
+ def optimize_strunicode_loop(self, ops, spectext, optops):
+ # check with the arguments passed in
+ self.optimize_loop(ops, spectext, optops)
+ # check with replacing 'str' with 'unicode' everywhere
+ self.optimize_loop(ops.replace('str','unicode').replace('s"', 'u"'),
+ spectext,
+ optops.replace('str','unicode').replace('s"', 'u"'))
+
def test_newstr_1(self):
ops = """
[i0]
@@ -3905,7 +3914,7 @@
[i0]
jump(i0)
"""
- self.optimize_loop(ops, 'Not', expected)
+ self.optimize_strunicode_loop(ops, 'Not', expected)
def test_newstr_2(self):
ops = """
@@ -3921,7 +3930,7 @@
[i0, i1]
jump(i1, i0)
"""
- self.optimize_loop(ops, 'Not, Not', expected)
+ self.optimize_strunicode_loop(ops, 'Not, Not', expected)
def test_str_concat_1(self):
ops = """
@@ -3942,7 +3951,7 @@
copystrcontent(p2, p3, 0, i4, i5)
jump(p2, p3)
"""
- self.optimize_loop(ops, 'Not, Not', expected)
+ self.optimize_strunicode_loop(ops, 'Not, Not', expected)
def test_str_concat_vstr2_str(self):
ops = """
@@ -3965,7 +3974,7 @@
copystrcontent(p2, p3, 0, 2, i4)
jump(i1, i0, p3)
"""
- self.optimize_loop(ops, 'Not, Not, Not', expected)
+ self.optimize_strunicode_loop(ops, 'Not, Not, Not', expected)
def test_str_concat_str_vstr2(self):
ops = """
@@ -3989,7 +3998,7 @@
i6 = int_add(i5, 1) # will be killed by the backend
jump(i1, i0, p3)
"""
- self.optimize_loop(ops, 'Not, Not, Not', expected)
+ self.optimize_strunicode_loop(ops, 'Not, Not, Not', expected)
def test_str_concat_str_str_str(self):
ops = """
@@ -4016,12 +4025,12 @@
copystrcontent(p3, p5, 0, i12b, i3b)
jump(p2, p3, p5)
"""
- self.optimize_loop(ops, 'Not, Not, Not', expected)
+ self.optimize_strunicode_loop(ops, 'Not, Not, Not', expected)
def test_str_concat_str_cstr1(self):
ops = """
[p2]
- p3 = call(0, p2, "x", descr=strconcatdescr)
+ p3 = call(0, p2, s"x", descr=strconcatdescr)
jump(p3)
"""
expected = """
@@ -4035,28 +4044,28 @@
i5 = int_add(i4, 1) # will be killed by the backend
jump(p3)
"""
- self.optimize_loop(ops, 'Not', expected)
+ self.optimize_strunicode_loop(ops, 'Not', expected)
def test_str_concat_consts(self):
ops = """
[]
- p1 = same_as("ab")
- p2 = same_as("cde")
+ p1 = same_as(s"ab")
+ p2 = same_as(s"cde")
p3 = call(0, p1, p2, descr=strconcatdescr)
escape(p3)
jump()
"""
expected = """
[]
- escape("abcde")
+ escape(s"abcde")
jump()
"""
- self.optimize_loop(ops, '', expected)
+ self.optimize_strunicode_loop(ops, '', expected)
def test_str_slice_1(self):
ops = """
[p1, i1, i2]
- p2 = call(0, p1, i1, i2, descr=slicedescr)
+ p2 = call(0, p1, i1, i2, descr=strslicedescr)
jump(p2, i1, i2)
"""
expected = """
@@ -4066,12 +4075,12 @@
copystrcontent(p1, p2, i1, 0, i3)
jump(p2, i1, i2)
"""
- self.optimize_loop(ops, 'Not, Not, Not', expected)
+ self.optimize_strunicode_loop(ops, 'Not, Not, Not', expected)
def test_str_slice_2(self):
ops = """
[p1, i2]
- p2 = call(0, p1, 0, i2, descr=slicedescr)
+ p2 = call(0, p1, 0, i2, descr=strslicedescr)
jump(p2, i2)
"""
expected = """
@@ -4080,13 +4089,13 @@
copystrcontent(p1, p2, 0, 0, i2)
jump(p2, i2)
"""
- self.optimize_loop(ops, 'Not, Not', expected)
+ self.optimize_strunicode_loop(ops, 'Not, Not', expected)
def test_str_slice_3(self):
ops = """
[p1, i1, i2, i3, i4]
- p2 = call(0, p1, i1, i2, descr=slicedescr)
- p3 = call(0, p2, i3, i4, descr=slicedescr)
+ p2 = call(0, p1, i1, i2, descr=strslicedescr)
+ p3 = call(0, p2, i3, i4, descr=strslicedescr)
jump(p3, i1, i2, i3, i4)
"""
expected = """
@@ -4098,12 +4107,12 @@
copystrcontent(p1, p3, i6, 0, i5)
jump(p3, i1, i2, i3, i4)
"""
- self.optimize_loop(ops, 'Not, Not, Not, Not, Not', expected)
+ self.optimize_strunicode_loop(ops, 'Not, Not, Not, Not, Not', expected)
def test_str_slice_getitem1(self):
ops = """
[p1, i1, i2, i3]
- p2 = call(0, p1, i1, i2, descr=slicedescr)
+ p2 = call(0, p1, i1, i2, descr=strslicedescr)
i4 = strgetitem(p2, i3)
escape(i4)
jump(p1, i1, i2, i3)
@@ -4116,7 +4125,7 @@
escape(i4)
jump(p1, i1, i2, i3)
"""
- self.optimize_loop(ops, 'Not, Not, Not, Not', expected)
+ self.optimize_strunicode_loop(ops, 'Not, Not, Not, Not', expected)
def test_str_slice_plain(self):
ops = """
@@ -4124,7 +4133,7 @@
p1 = newstr(2)
strsetitem(p1, 0, i3)
strsetitem(p1, 1, i4)
- p2 = call(0, p1, 1, 2, descr=slicedescr)
+ p2 = call(0, p1, 1, 2, descr=strslicedescr)
i5 = strgetitem(p2, 0)
escape(i5)
jump(i3, i4)
@@ -4134,12 +4143,12 @@
escape(i4)
jump(i3, i4)
"""
- self.optimize_loop(ops, 'Not, Not', expected)
+ self.optimize_strunicode_loop(ops, 'Not, Not', expected)
def test_str_slice_concat(self):
ops = """
[p1, i1, i2, p2]
- p3 = call(0, p1, i1, i2, descr=slicedescr)
+ p3 = call(0, p1, i1, i2, descr=strslicedescr)
p4 = call(0, p3, p2, descr=strconcatdescr)
jump(p4, i1, i2, p2)
"""
@@ -4155,10 +4164,10 @@
copystrcontent(p2, p4, 0, i3, i4b)
jump(p4, i1, i2, p2)
"""
- self.optimize_loop(ops, 'Not, Not, Not, Not', expected)
+ self.optimize_strunicode_loop(ops, 'Not, Not, Not, Not', expected)
# ----------
- def optimize_loop_extradescrs(self, ops, spectext, optops):
+ def optimize_strunicode_loop_extradescrs(self, ops, spectext, optops):
from pypy.jit.metainterp.optimizeopt import string
def my_callinfo_for_oopspec(oopspecindex):
calldescrtype = type(LLtypeMixin.strequaldescr)
@@ -4173,7 +4182,7 @@
saved = string.callinfo_for_oopspec
try:
string.callinfo_for_oopspec = my_callinfo_for_oopspec
- self.optimize_loop(ops, spectext, optops)
+ self.optimize_strunicode_loop(ops, spectext, optops)
finally:
string.callinfo_for_oopspec = saved
@@ -4184,7 +4193,7 @@
escape(i0)
jump(p1, p2)
"""
- self.optimize_loop_extradescrs(ops, 'Not, Not', ops)
+ self.optimize_strunicode_loop_extradescrs(ops, 'Not, Not', ops)
def test_str_equal_noop2(self):
ops = """
@@ -4209,12 +4218,13 @@
escape(i0)
jump(p1, p2, p3)
"""
- self.optimize_loop_extradescrs(ops, 'Not, Not, Not', expected)
+ self.optimize_strunicode_loop_extradescrs(ops, 'Not, Not, Not',
+ expected)
def test_str_equal_slice1(self):
ops = """
[p1, i1, i2, p3]
- p4 = call(0, p1, i1, i2, descr=slicedescr)
+ p4 = call(0, p1, i1, i2, descr=strslicedescr)
i0 = call(0, p4, p3, descr=strequaldescr)
escape(i0)
jump(p1, i1, i2, p3)
@@ -4226,12 +4236,13 @@
escape(i0)
jump(p1, i1, i2, p3)
"""
- self.optimize_loop_extradescrs(ops, 'Not, Not, Not, Not', expected)
+ self.optimize_strunicode_loop_extradescrs(ops, 'Not, Not, Not, Not',
+ expected)
def test_str_equal_slice2(self):
ops = """
[p1, i1, i2, p3]
- p4 = call(0, p1, i1, i2, descr=slicedescr)
+ p4 = call(0, p1, i1, i2, descr=strslicedescr)
i0 = call(0, p3, p4, descr=strequaldescr)
escape(i0)
jump(p1, i1, i2, p3)
@@ -4243,13 +4254,14 @@
escape(i0)
jump(p1, i1, i2, p3)
"""
- self.optimize_loop_extradescrs(ops, 'Not, Not, Not, Not', expected)
+ self.optimize_strunicode_loop_extradescrs(ops, 'Not, Not, Not, Not',
+ expected)
def test_str_equal_slice3(self):
ops = """
[p1, i1, i2, p3]
guard_nonnull(p3) []
- p4 = call(0, p1, i1, i2, descr=slicedescr)
+ p4 = call(0, p1, i1, i2, descr=strslicedescr)
i0 = call(0, p3, p4, descr=strequaldescr)
escape(i0)
jump(p1, i1, i2, p3)
@@ -4262,13 +4274,14 @@
escape(i0)
jump(p1, i1, i2, p3)
"""
- self.optimize_loop_extradescrs(ops, 'Not, Not, Not, Not', expected)
+ self.optimize_strunicode_loop_extradescrs(ops, 'Not, Not, Not, Not',
+ expected)
def test_str_equal_slice4(self):
ops = """
[p1, i1, i2]
- p3 = call(0, p1, i1, i2, descr=slicedescr)
- i0 = call(0, p3, "x", descr=strequaldescr)
+ p3 = call(0, p1, i1, i2, descr=strslicedescr)
+ i0 = call(0, p3, s"x", descr=strequaldescr)
escape(i0)
jump(p1, i1, i2)
"""
@@ -4279,12 +4292,13 @@
escape(i0)
jump(p1, i1, i2)
"""
- self.optimize_loop_extradescrs(ops, 'Not, Not, Not', expected)
+ self.optimize_strunicode_loop_extradescrs(ops, 'Not, Not, Not',
+ expected)
def test_str_equal_slice5(self):
ops = """
[p1, i1, i2, i3]
- p4 = call(0, p1, i1, i2, descr=slicedescr)
+ p4 = call(0, p1, i1, i2, descr=strslicedescr)
p5 = newstr(1)
strsetitem(p5, 0, i3)
i0 = call(0, p5, p4, descr=strequaldescr)
@@ -4298,7 +4312,8 @@
escape(i0)
jump(p1, i1, i2, i3)
"""
- self.optimize_loop_extradescrs(ops, 'Not, Not, Not, Not', expected)
+ self.optimize_strunicode_loop_extradescrs(ops, 'Not, Not, Not, Not',
+ expected)
def test_str_equal_none1(self):
ops = """
@@ -4313,7 +4328,7 @@
escape(i0)
jump(p1)
"""
- self.optimize_loop_extradescrs(ops, 'Not', expected)
+ self.optimize_strunicode_loop_extradescrs(ops, 'Not', expected)
def test_str_equal_none2(self):
ops = """
@@ -4328,30 +4343,30 @@
escape(i0)
jump(p1)
"""
- self.optimize_loop_extradescrs(ops, 'Not', expected)
+ self.optimize_strunicode_loop_extradescrs(ops, 'Not', expected)
def test_str_equal_nonnull1(self):
ops = """
[p1]
guard_nonnull(p1) []
- i0 = call(0, p1, "hello world", descr=strequaldescr)
+ i0 = call(0, p1, s"hello world", descr=strequaldescr)
escape(i0)
jump(p1)
"""
expected = """
[p1]
guard_nonnull(p1) []
- i0 = call(0, p1, "hello world", descr=streq_nonnull_descr)
+ i0 = call(0, p1, s"hello world", descr=streq_nonnull_descr)
escape(i0)
jump(p1)
"""
- self.optimize_loop_extradescrs(ops, 'Not', expected)
+ self.optimize_strunicode_loop_extradescrs(ops, 'Not', expected)
def test_str_equal_nonnull2(self):
ops = """
[p1]
guard_nonnull(p1) []
- i0 = call(0, p1, "", descr=strequaldescr)
+ i0 = call(0, p1, s"", descr=strequaldescr)
escape(i0)
jump(p1)
"""
@@ -4363,13 +4378,13 @@
escape(i0)
jump(p1)
"""
- self.optimize_loop_extradescrs(ops, 'Not', expected)
+ self.optimize_strunicode_loop_extradescrs(ops, 'Not', expected)
def test_str_equal_nonnull3(self):
ops = """
[p1]
guard_nonnull(p1) []
- i0 = call(0, p1, "x", descr=strequaldescr)
+ i0 = call(0, p1, s"x", descr=strequaldescr)
escape(i0)
jump(p1)
"""
@@ -4380,13 +4395,13 @@
escape(i0)
jump(p1)
"""
- self.optimize_loop_extradescrs(ops, 'Not', expected)
+ self.optimize_strunicode_loop_extradescrs(ops, 'Not', expected)
def test_str_equal_nonnull4(self):
ops = """
[p1, p2]
p4 = call(0, p1, p2, descr=strconcatdescr)
- i0 = call(0, "hello world", p4, descr=strequaldescr)
+ i0 = call(0, s"hello world", p4, descr=strequaldescr)
escape(i0)
jump(p1, p2)
"""
@@ -4401,17 +4416,17 @@
i5 = strlen(p2)
i6 = int_add(i4, i5) # will be killed by the backend
copystrcontent(p2, p4, 0, i4, i5)
- i0 = call(0, "hello world", p4, descr=streq_nonnull_descr)
+ i0 = call(0, s"hello world", p4, descr=streq_nonnull_descr)
escape(i0)
jump(p1, p2)
"""
- self.optimize_loop_extradescrs(ops, 'Not, Not', expected)
+ self.optimize_strunicode_loop_extradescrs(ops, 'Not, Not', expected)
def test_str_equal_chars0(self):
ops = """
[i1]
p1 = newstr(0)
- i0 = call(0, p1, "", descr=strequaldescr)
+ i0 = call(0, p1, s"", descr=strequaldescr)
escape(i0)
jump(i1)
"""
@@ -4420,14 +4435,14 @@
escape(1)
jump(i1)
"""
- self.optimize_loop_extradescrs(ops, 'Not', expected)
+ self.optimize_strunicode_loop_extradescrs(ops, 'Not', expected)
def test_str_equal_chars1(self):
ops = """
[i1]
p1 = newstr(1)
strsetitem(p1, 0, i1)
- i0 = call(0, p1, "x", descr=strequaldescr)
+ i0 = call(0, p1, s"x", descr=strequaldescr)
escape(i0)
jump(i1)
"""
@@ -4437,7 +4452,7 @@
escape(i0)
jump(i1)
"""
- self.optimize_loop_extradescrs(ops, 'Not', expected)
+ self.optimize_strunicode_loop_extradescrs(ops, 'Not', expected)
def test_str_equal_chars2(self):
ops = """
@@ -4445,7 +4460,7 @@
p1 = newstr(2)
strsetitem(p1, 0, i1)
strsetitem(p1, 1, i2)
- i0 = call(0, p1, "xy", descr=strequaldescr)
+ i0 = call(0, p1, s"xy", descr=strequaldescr)
escape(i0)
jump(i1, i2)
"""
@@ -4454,16 +4469,16 @@
p1 = newstr(2)
strsetitem(p1, 0, i1)
strsetitem(p1, 1, i2)
- i0 = call(0, p1, "xy", descr=streq_lengthok_descr)
+ i0 = call(0, p1, s"xy", descr=streq_lengthok_descr)
escape(i0)
jump(i1, i2)
"""
- self.optimize_loop_extradescrs(ops, 'Not, Not', expected)
+ self.optimize_strunicode_loop_extradescrs(ops, 'Not, Not', expected)
def test_str_equal_chars3(self):
ops = """
[p1]
- i0 = call(0, "x", p1, descr=strequaldescr)
+ i0 = call(0, s"x", p1, descr=strequaldescr)
escape(i0)
jump(p1)
"""
@@ -4473,14 +4488,14 @@
escape(i0)
jump(p1)
"""
- self.optimize_loop_extradescrs(ops, 'Not', expected)
+ self.optimize_strunicode_loop_extradescrs(ops, 'Not', expected)
def test_str_equal_lengthmismatch1(self):
ops = """
[i1]
p1 = newstr(1)
strsetitem(p1, 0, i1)
- i0 = call(0, "xy", p1, descr=strequaldescr)
+ i0 = call(0, s"xy", p1, descr=strequaldescr)
escape(i0)
jump(i1)
"""
@@ -4489,10 +4504,33 @@
escape(0)
jump(i1)
"""
- self.optimize_loop_extradescrs(ops, 'Not', expected)
+ self.optimize_strunicode_loop_extradescrs(ops, 'Not', expected)
- # XXX unicode operations
- # XXX str2unicode
+ def test_str2unicode_constant(self):
+ ops = """
+ []
+ p0 = call(0, "xy", descr=s2u_descr) # string -> unicode
+ escape(p0)
+ jump()
+ """
+ expected = """
+ []
+ escape(u"xy")
+ jump()
+ """
+ self.optimize_strunicode_loop_extradescrs(ops, '', expected)
+
+ def test_str2unicode_nonconstant(self):
+ ops = """
+ [p0]
+ p1 = call(0, p0, descr=s2u_descr) # string -> unicode
+ escape(p1)
+ jump(p1)
+ """
+ self.optimize_strunicode_loop_extradescrs(ops, 'Not', ops)
+ # more generally, supporting non-constant but virtual cases is
+ # not obvious, because of the exception UnicodeDecodeError that
+ # can be raised by ll_str2unicode()
##class TestOOtype(BaseTestOptimizeOpt, OOtypeMixin):
Modified: pypy/branch/jit-str-unicode/pypy/jit/metainterp/test/test_resume.py
==============================================================================
--- pypy/branch/jit-str-unicode/pypy/jit/metainterp/test/test_resume.py (original)
+++ pypy/branch/jit-str-unicode/pypy/jit/metainterp/test/test_resume.py Mon Oct 11 14:26:19 2010
@@ -240,6 +240,17 @@
return FakeBuiltObject(strconcat=[left, right])
def slice_string(self, str, start, length):
return FakeBuiltObject(strslice=[str, start, length])
+ def allocate_unicode(self, length):
+ return FakeBuiltObject(unistring=[None]*length)
+ def unicode_setitem(self, unistring, i, fieldnum):
+ value, tag = untag(fieldnum)
+ assert tag == TAGINT
+ assert 0 <= i < len(unistring.unistring)
+ unistring.unistring[i] = value
+ def concat_unicodes(self, left, right):
+ return FakeBuiltObject(uniconcat=[left, right])
+ def slice_unicode(self, str, start, length):
+ return FakeBuiltObject(unislice=[str, start, length])
class FakeBuiltObject(object):
def __init__(self, **kwds):
@@ -304,6 +315,30 @@
assert reader.force_all_virtuals() == [
FakeBuiltObject(strslice=info.fieldnums)]
+def test_vuniplaininfo():
+ info = VUniPlainInfo()
+ info.fieldnums = [tag(60, TAGINT)]
+ reader = FakeResumeDataReader()
+ reader._prepare_virtuals([info])
+ assert reader.force_all_virtuals() == [
+ FakeBuiltObject(unistring=[60])]
+
+def test_vuniconcatinfo():
+ info = VUniConcatInfo()
+ info.fieldnums = [tag(10, TAGBOX), tag(20, TAGBOX)]
+ reader = FakeResumeDataReader()
+ reader._prepare_virtuals([info])
+ assert reader.force_all_virtuals() == [
+ FakeBuiltObject(uniconcat=info.fieldnums)]
+
+def test_vunisliceinfo():
+ info = VUniSliceInfo()
+ info.fieldnums = [tag(10, TAGBOX), tag(20, TAGBOX), tag(30, TAGBOX)]
+ reader = FakeResumeDataReader()
+ reader._prepare_virtuals([info])
+ assert reader.force_all_virtuals() == [
+ FakeBuiltObject(unislice=info.fieldnums)]
+
# ____________________________________________________________
Modified: pypy/branch/jit-str-unicode/pypy/jit/metainterp/test/test_string.py
==============================================================================
--- pypy/branch/jit-str-unicode/pypy/jit/metainterp/test/test_string.py (original)
+++ pypy/branch/jit-str-unicode/pypy/jit/metainterp/test/test_string.py Mon Oct 11 14:26:19 2010
@@ -6,14 +6,17 @@
class StringTests:
+ _str, _chr = str, chr
+
def test_eq_residual(self):
+ _str = self._str
jitdriver = JitDriver(greens = [], reds = ['n', 'i', 's'])
- global_s = "hello"
+ global_s = _str("hello")
def f(n, b, s):
if b:
- s += "ello"
+ s += _str("ello")
else:
- s += "allo"
+ s += _str("allo")
i = 0
while n > 0:
jitdriver.can_enter_jit(s=s, n=n, i=i)
@@ -21,18 +24,19 @@
n -= 1 + (s == global_s)
i += 1
return i
- res = self.meta_interp(f, [10, True, 'h'], listops=True)
+ res = self.meta_interp(f, [10, True, _str('h')], listops=True)
assert res == 5
self.check_loops(**{self.CALL: 1, self.CALL_PURE: 0})
def test_eq_folded(self):
+ _str = self._str
jitdriver = JitDriver(greens = ['s'], reds = ['n', 'i'])
- global_s = "hello"
+ global_s = _str("hello")
def f(n, b, s):
if b:
- s += "ello"
+ s += _str("ello")
else:
- s += "allo"
+ s += _str("allo")
i = 0
while n > 0:
jitdriver.can_enter_jit(s=s, n=n, i=i)
@@ -40,31 +44,18 @@
n -= 1 + (s == global_s)
i += 1
return i
- res = self.meta_interp(f, [10, True, 'h'], listops=True)
+ res = self.meta_interp(f, [10, True, _str('h')], listops=True)
assert res == 5
self.check_loops(**{self.CALL: 0, self.CALL_PURE: 0})
def test_newstr(self):
+ _str, _chr = self._str, self._chr
jitdriver = JitDriver(greens = [], reds = ['n', 'm'])
def f(n, m):
while True:
jitdriver.can_enter_jit(m=m, n=n)
jitdriver.jit_merge_point(m=m, n=n)
- bytecode = 'adlfkj' + chr(n)
- res = bytecode[n]
- m -= 1
- if m < 0:
- return ord(res)
- res = self.meta_interp(f, [6, 10])
- assert res == 6
-
- def test_newunicode(self):
- jitdriver = JitDriver(greens = [], reds = ['n', 'm'])
- def f(n, m):
- while True:
- jitdriver.can_enter_jit(m=m, n=n)
- jitdriver.jit_merge_point(m=m, n=n)
- bytecode = u'adlfkj' + unichr(n)
+ bytecode = _str('adlfkj') + _chr(n)
res = bytecode[n]
m -= 1
if m < 0:
@@ -73,95 +64,96 @@
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)
+ _str, _chr = self._str, self._chr
+ 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 = _chr(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
+ _str, _chr = self._str, self._chr
+ 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 = _chr(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)
+ _str, _chr = self._str, self._chr
+ 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 = _chr(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_strconcat_pure(self):
- for somestr in ["abc", ]: #u"def"]:
- jitdriver = JitDriver(greens = [], reds = ['m', 'n'])
- @dont_look_inside
- def escape(x):
- pass
- mylist = [somestr+str(i) for i in range(10)]
- def f(n, m):
- while m >= 0:
- jitdriver.can_enter_jit(m=m, n=n)
- jitdriver.jit_merge_point(m=m, n=n)
- s = mylist[n] + mylist[m]
- if m > 100:
- escape(s)
- m -= 1
- return 42
- self.meta_interp(f, [6, 7])
- self.check_loops(newstr=0, strsetitem=0,
- newunicode=0, unicodesetitem=0,
- call=0, call_pure=0)
+ _str = self._str
+ jitdriver = JitDriver(greens = [], reds = ['m', 'n'])
+ @dont_look_inside
+ def escape(x):
+ pass
+ mylist = [_str("abc") + _str(i) for i in range(10)]
+ def f(n, m):
+ while m >= 0:
+ jitdriver.can_enter_jit(m=m, n=n)
+ jitdriver.jit_merge_point(m=m, n=n)
+ s = mylist[n] + mylist[m]
+ if m > 100:
+ escape(s)
+ m -= 1
+ return 42
+ self.meta_interp(f, [6, 7])
+ self.check_loops(newstr=0, strsetitem=0,
+ newunicode=0, unicodesetitem=0,
+ call=0, call_pure=0)
def test_strconcat_escape_str_str(self):
+ _str = self._str
jitdriver = JitDriver(greens = [], reds = ['m', 'n'])
@dont_look_inside
def escape(x):
pass
- mylist = ["somestr"+str(i) for i in range(10)]
+ mylist = [_str("somestr") + _str(i) for i in range(10)]
def f(n, m):
while m >= 0:
jitdriver.can_enter_jit(m=m, n=n)
@@ -171,46 +163,64 @@
m -= 1
return 42
self.meta_interp(f, [6, 7])
- self.check_loops(newstr=1, strsetitem=0, copystrcontent=2,
- call=1, call_pure=0) # escape
+ if _str is str:
+ self.check_loops(newstr=1, strsetitem=0, copystrcontent=2,
+ call=1, call_pure=0) # escape
+ else:
+ self.check_loops(newunicode=1, unicodesetitem=0,
+ copyunicodecontent=2,
+ call=1, call_pure=0) # escape
def test_strconcat_escape_str_char(self):
+ _str, _chr = self._str, self._chr
jitdriver = JitDriver(greens = [], reds = ['m', 'n'])
@dont_look_inside
def escape(x):
pass
- mylist = ["somestr"+str(i) for i in range(10)]
+ mylist = [_str("somestr") + _str(i) for i in range(10)]
def f(n, m):
while m >= 0:
jitdriver.can_enter_jit(m=m, n=n)
jitdriver.jit_merge_point(m=m, n=n)
- s = mylist[n] + chr(m)
+ s = mylist[n] + _chr(m)
escape(s)
m -= 1
return 42
self.meta_interp(f, [6, 7])
- self.check_loops(newstr=1, strsetitem=1, copystrcontent=1,
- call=1, call_pure=0) # escape
+ if _str is str:
+ self.check_loops(newstr=1, strsetitem=1, copystrcontent=1,
+ call=1, call_pure=0) # escape
+ else:
+ self.check_loops(newunicode=1, unicodesetitem=1,
+ copyunicodecontent=1,
+ call=1, call_pure=0) # escape
def test_strconcat_escape_char_str(self):
+ _str, _chr = self._str, self._chr
jitdriver = JitDriver(greens = [], reds = ['m', 'n'])
@dont_look_inside
def escape(x):
pass
- mylist = ["somestr"+str(i) for i in range(10)]
+ mylist = [_str("somestr") + _str(i) for i in range(10)]
def f(n, m):
while m >= 0:
jitdriver.can_enter_jit(m=m, n=n)
jitdriver.jit_merge_point(m=m, n=n)
- s = chr(n) + mylist[m]
+ s = _chr(n) + mylist[m]
escape(s)
m -= 1
return 42
self.meta_interp(f, [6, 7])
- self.check_loops(newstr=1, strsetitem=1, copystrcontent=1,
- call=1, call_pure=0) # escape
+ if _str is str:
+ self.check_loops(newstr=1, strsetitem=1, copystrcontent=1,
+ call=1, call_pure=0) # escape
+ else:
+ self.check_loops(newunicode=1, unicodesetitem=1,
+ copyunicodecontent=1,
+ call=1, call_pure=0) # escape
def test_strconcat_escape_char_char(self):
+ _str, _chr = self._str, self._chr
jitdriver = JitDriver(greens = [], reds = ['m', 'n'])
@dont_look_inside
def escape(x):
@@ -219,91 +229,132 @@
while m >= 0:
jitdriver.can_enter_jit(m=m, n=n)
jitdriver.jit_merge_point(m=m, n=n)
- s = chr(n) + chr(m)
+ s = _chr(n) + _chr(m)
escape(s)
m -= 1
return 42
self.meta_interp(f, [6, 7])
- self.check_loops(newstr=1, strsetitem=2, copystrcontent=0,
- call=1, call_pure=0) # escape
+ if _str is str:
+ self.check_loops(newstr=1, strsetitem=2, copystrcontent=0,
+ call=1, call_pure=0) # escape
+ else:
+ self.check_loops(newunicode=1, unicodesetitem=2,
+ copyunicodecontent=0,
+ call=1, call_pure=0) # escape
def test_strconcat_escape_str_char_str(self):
+ _str, _chr = self._str, self._chr
jitdriver = JitDriver(greens = [], reds = ['m', 'n'])
@dont_look_inside
def escape(x):
pass
- mylist = ["somestr"+str(i) for i in range(10)]
+ mylist = [_str("somestr") + _str(i) for i in range(10)]
def f(n, m):
while m >= 0:
jitdriver.can_enter_jit(m=m, n=n)
jitdriver.jit_merge_point(m=m, n=n)
- s = mylist[n] + chr(n) + mylist[m]
+ s = mylist[n] + _chr(n) + mylist[m]
escape(s)
m -= 1
return 42
self.meta_interp(f, [6, 7])
- self.check_loops(newstr=1, strsetitem=1, copystrcontent=2,
- call=1, call_pure=0) # escape
+ if _str is str:
+ self.check_loops(newstr=1, strsetitem=1, copystrcontent=2,
+ call=1, call_pure=0) # escape
+ else:
+ self.check_loops(newunicode=1, unicodesetitem=1,
+ copyunicodecontent=2,
+ call=1, call_pure=0) # escape
def test_strconcat_guard_fail(self):
- for somestr in ["abc", ]: #u"def"]:
- jitdriver = JitDriver(greens = [], reds = ['m', 'n'])
- @dont_look_inside
- def escape(x):
- pass
- mylist = [somestr+str(i) for i in range(12)]
- def f(n, m):
- while m >= 0:
- jitdriver.can_enter_jit(m=m, n=n)
- jitdriver.jit_merge_point(m=m, n=n)
- s = mylist[n] + mylist[m]
- if m & 1:
- escape(s)
- m -= 1
- return 42
- self.meta_interp(f, [6, 10])
+ _str = self._str
+ jitdriver = JitDriver(greens = [], reds = ['m', 'n'])
+ @dont_look_inside
+ def escape(x):
+ pass
+ mylist = [_str("abc") + _str(i) for i in range(12)]
+ def f(n, m):
+ while m >= 0:
+ jitdriver.can_enter_jit(m=m, n=n)
+ jitdriver.jit_merge_point(m=m, n=n)
+ s = mylist[n] + mylist[m]
+ if m & 1:
+ escape(s)
+ m -= 1
+ return 42
+ self.meta_interp(f, [6, 10])
def test_strslice(self):
- for somestr in ["abc", ]: #u"def"]:
- jitdriver = JitDriver(greens = [], reds = ['m', 'n'])
- @dont_look_inside
- def escape(x):
- pass
- def f(n, m):
- assert n >= 0
- while m >= 0:
- jitdriver.can_enter_jit(m=m, n=n)
- jitdriver.jit_merge_point(m=m, n=n)
- s = "foobarbazetc"[m:n]
- if m <= 5:
- escape(s)
- m -= 1
- return 42
- self.meta_interp(f, [10, 10])
+ _str = self._str
+ longstring = _str("foobarbazetc")
+ jitdriver = JitDriver(greens = [], reds = ['m', 'n'])
+ @dont_look_inside
+ def escape(x):
+ pass
+ def f(n, m):
+ assert n >= 0
+ while m >= 0:
+ jitdriver.can_enter_jit(m=m, n=n)
+ jitdriver.jit_merge_point(m=m, n=n)
+ s = longstring[m:n]
+ if m <= 5:
+ escape(s)
+ m -= 1
+ return 42
+ self.meta_interp(f, [10, 10])
def test_streq_char(self):
- for somestr in ["?abcdefg", ]: #u"def"]:
- jitdriver = JitDriver(greens = [], reds = ['m', 'n'])
- @dont_look_inside
- def escape(x):
- pass
- def f(n, m):
- assert n >= 0
- while m >= 0:
- jitdriver.can_enter_jit(m=m, n=n)
- jitdriver.jit_merge_point(m=m, n=n)
- s = somestr[:m]
- escape(s == "?")
- m -= 1
- return 42
- self.meta_interp(f, [6, 7])
- self.check_loops(newstr=0, newunicode=0)
-
-
-class TestOOtype(StringTests, OOJitMixin):
- CALL = "oosend"
- CALL_PURE = "oosend_pure"
+ _str = self._str
+ longstring = _str("?abcdefg")
+ somechar = _str("?")
+ jitdriver = JitDriver(greens = [], reds = ['m', 'n'])
+ @dont_look_inside
+ def escape(x):
+ pass
+ def f(n, m):
+ assert n >= 0
+ while m >= 0:
+ jitdriver.can_enter_jit(m=m, n=n)
+ jitdriver.jit_merge_point(m=m, n=n)
+ s = longstring[:m]
+ escape(s == somechar)
+ m -= 1
+ return 42
+ self.meta_interp(f, [6, 7])
+ self.check_loops(newstr=0, newunicode=0)
+
+
+#class TestOOtype(StringTests, OOJitMixin):
+# CALL = "oosend"
+# CALL_PURE = "oosend_pure"
class TestLLtype(StringTests, LLJitMixin):
CALL = "call"
CALL_PURE = "call_pure"
+
+class TestLLtypeUnicode(TestLLtype):
+ _str, _chr = unicode, unichr
+
+ def test_str2unicode(self):
+ _str = self._str
+ jitdriver = JitDriver(greens = [], reds = ['m', 'n'])
+ class Foo:
+ pass
+ @dont_look_inside
+ def escape(x):
+ assert x == _str("6y")
+ def f(n, m):
+ while m >= 0:
+ jitdriver.can_enter_jit(m=m, n=n)
+ jitdriver.jit_merge_point(m=m, n=n)
+ foo = Foo()
+ foo.y = chr(m)
+ foo.y = "y"
+ s = _str(str(n)) + _str(foo.y)
+ escape(s)
+ m -= 1
+ return 42
+ self.meta_interp(f, [6, 7])
+ self.check_loops(call=3, # str(), _str(), escape()
+ newunicode=1, unicodegetitem=0,
+ unicodesetitem=1, copyunicodecontent=1)
More information about the Pypy-commit
mailing list