[pypy-commit] pypy arm-backend-2: merge default up to 9439564ba9b3

bivab noreply at buildbot.pypy.org
Fri Jun 24 17:39:54 CEST 2011


Author: David Schneider <david.schneider at picle.org>
Branch: arm-backend-2
Changeset: r45106:4a9f1f42a77b
Date: 2011-06-24 16:54 +0200
http://bitbucket.org/pypy/pypy/changeset/4a9f1f42a77b/

Log:	merge default up to 9439564ba9b3

diff --git a/pypy/annotation/test/test_annrpython.py b/pypy/annotation/test/test_annrpython.py
--- a/pypy/annotation/test/test_annrpython.py
+++ b/pypy/annotation/test/test_annrpython.py
@@ -43,8 +43,8 @@
 
 
 class TestAnnotateTestCase:
-    def setup_class(cls): 
-        cls.space = FlowObjSpace() 
+    def setup_class(cls):
+        cls.space = FlowObjSpace()
 
     def teardown_method(self, meth):
         assert annmodel.s_Bool == annmodel.SomeBool()
@@ -263,7 +263,7 @@
         getcdef = a.bookkeeper.getuniqueclassdef
         assert getcdef(snippet.F).attrs.keys() == ['m']
         assert getcdef(snippet.G).attrs.keys() == ['m2']
-        assert getcdef(snippet.H).attrs.keys() == ['attr'] 
+        assert getcdef(snippet.H).attrs.keys() == ['attr']
         assert getcdef(snippet.H).about_attribute('attr') == (
                           a.bookkeeper.immutablevalue(1))
 
@@ -390,34 +390,34 @@
     def test_tuple_unpack_from_const_tuple_with_different_types(self):
         a = self.RPythonAnnotator()
         s = a.build_types(snippet.func_arg_unpack, [])
-        assert isinstance(s, annmodel.SomeInteger) 
-        assert s.const == 3 
+        assert isinstance(s, annmodel.SomeInteger)
+        assert s.const == 3
 
     def test_pbc_attr_preserved_on_instance(self):
         a = self.RPythonAnnotator()
         s = a.build_types(snippet.preserve_pbc_attr_on_instance, [bool])
         #a.simplify()
         #a.translator.view()
-        assert s == annmodel.SomeInteger(nonneg=True) 
-        #self.assertEquals(s.__class__, annmodel.SomeInteger) 
+        assert s == annmodel.SomeInteger(nonneg=True)
+        #self.assertEquals(s.__class__, annmodel.SomeInteger)
 
     def test_pbc_attr_preserved_on_instance_with_slots(self):
         a = self.RPythonAnnotator()
         s = a.build_types(snippet.preserve_pbc_attr_on_instance_with_slots,
                           [bool])
-        assert s == annmodel.SomeInteger(nonneg=True) 
-
-    def test_is_and_knowntype_data(self): 
+        assert s == annmodel.SomeInteger(nonneg=True)
+
+    def test_is_and_knowntype_data(self):
         a = self.RPythonAnnotator()
         s = a.build_types(snippet.is_and_knowntype, [str])
         #a.simplify()
         #a.translator.view()
         assert s == a.bookkeeper.immutablevalue(None)
 
-    def test_isinstance_and_knowntype_data(self): 
+    def test_isinstance_and_knowntype_data(self):
         a = self.RPythonAnnotator()
         x = a.bookkeeper.immutablevalue(snippet.apbc)
-        s = a.build_types(snippet.isinstance_and_knowntype, [x]) 
+        s = a.build_types(snippet.isinstance_and_knowntype, [x])
         #a.simplify()
         #a.translator.view()
         assert s == x
@@ -434,8 +434,8 @@
         # the annotator (it doesn't check that they operate property, though)
         for example, methname, s_example in [
             ('', 'join',    annmodel.SomeString()),
-            ([], 'append',  somelist()), 
-            ([], 'extend',  somelist()),           
+            ([], 'append',  somelist()),
+            ([], 'extend',  somelist()),
             ([], 'reverse', somelist()),
             ([], 'insert',  somelist()),
             ([], 'pop',     somelist()),
@@ -465,6 +465,13 @@
         assert isinstance(s, annmodel.SomeList)
         assert s.listdef.listitem.resized
 
+    def test_str_mul(self):
+        a = self.RPythonAnnotator()
+        def f(a_str):
+            return a_str * 3
+        s = a.build_types(f, [str])
+        assert isinstance(s, annmodel.SomeString)
+
     def test_simple_slicing(self):
         a = self.RPythonAnnotator()
         s = a.build_types(snippet.simple_slice, [list])
@@ -474,7 +481,7 @@
         a = self.RPythonAnnotator()
         s = a.build_types(snippet.simple_iter, [list])
         assert isinstance(s, annmodel.SomeIterator)
-        
+
     def test_simple_iter_next(self):
         def f(x):
             i = iter(range(x))
@@ -498,7 +505,7 @@
         assert listitem(s).knowntype == tuple
         assert listitem(s).items[0].knowntype == int
         assert listitem(s).items[1].knowntype == str
-        
+
     def test_dict_copy(self):
         a = self.RPythonAnnotator()
         t = somedict(annmodel.SomeInteger(), annmodel.SomeInteger())
@@ -544,7 +551,7 @@
         a = self.RPythonAnnotator()
         s = a.build_types(snippet.dict_values, [])
         assert isinstance(listitem(s), annmodel.SomeString)
-    
+
     def test_dict_values2(self):
         a = self.RPythonAnnotator()
         s = a.build_types(snippet.dict_values2, [])
@@ -570,19 +577,19 @@
         assert isinstance(dictkey(s), annmodel.SomeString)
         assert isinstance(dictvalue(s), annmodel.SomeInteger)
         assert not dictvalue(s).nonneg
-        
+
     def test_exception_deduction(self):
         a = self.RPythonAnnotator()
         s = a.build_types(snippet.exception_deduction, [])
         assert isinstance(s, annmodel.SomeInstance)
         assert s.classdef is a.bookkeeper.getuniqueclassdef(snippet.Exc)
-        
+
     def test_exception_deduction_we_are_dumb(self):
         a = self.RPythonAnnotator()
         s = a.build_types(snippet.exception_deduction_we_are_dumb, [])
         assert isinstance(s, annmodel.SomeInstance)
         assert s.classdef is a.bookkeeper.getuniqueclassdef(snippet.Exc)
-        
+
     def test_nested_exception_deduction(self):
         a = self.RPythonAnnotator()
         s = a.build_types(snippet.nested_exception_deduction, [])
@@ -645,8 +652,8 @@
         assert Rdef.attrs['r'].s_value.classdef == Rdef
         assert Rdef.attrs['n'].s_value.knowntype == int
         assert Rdef.attrs['m'].s_value.knowntype == int
-    
-        
+
+
     def test_propagation_of_fresh_instances_through_attrs_rec_eo(self):
         a = self.RPythonAnnotator()
         s = a.build_types(snippet.make_eo, [int])
@@ -958,7 +965,7 @@
             f1(1,2)
             g(f2)
             g(f3)
-        
+
         a = self.RPythonAnnotator()
         s = a.build_types(h, [])
 
@@ -1022,7 +1029,7 @@
         famA_m = mdescA_m.getcallfamily()
         famC_m = mdescC_m.getcallfamily()
         famB_n = mdescB_n.getcallfamily()
-        
+
         assert famA_m is famC_m
         assert famB_n is not famA_m
 
@@ -1038,7 +1045,7 @@
         gfCinit = graphof(a, C.__init__.im_func)
 
         assert famCinit.calltables == {(1, (), False, False): [{mdescCinit.funcdesc: gfCinit}] }
-        
+
     def test_isinstance_usigned(self):
         def f(x):
             return isinstance(x, r_uint)
@@ -1085,7 +1092,7 @@
         s = a.build_types(f, [])
         C1df = a.bookkeeper.getuniqueclassdef(C1)
         C2df = a.bookkeeper.getuniqueclassdef(C2)
-        
+
         assert s.items[0].classdef == C1df
         assert s.items[1].classdef == C2df
 
@@ -1098,29 +1105,29 @@
         assert a.binding(graph2.getreturnvar()).classdef == C2df
         assert graph1 in a.translator.graphs
         assert graph2 in a.translator.graphs
-    
+
     def test_specialcase_args(self):
         class C1(object):
             pass
-        
+
         class C2(object):
             pass
-        
+
         def alloc(cls, cls2):
             i = cls()
             assert isinstance(i, cls)
             j = cls2()
             assert isinstance(j, cls2)
             return i
-        
+
         def f():
             alloc(C1, C1)
             alloc(C1, C2)
             alloc(C2, C1)
             alloc(C2, C2)
-        
+
         alloc._annspecialcase_ = "specialize:arg(0,1)"
-        
+
         a = self.RPythonAnnotator()
         C1df = a.bookkeeper.getuniqueclassdef(C1)
         C2df = a.bookkeeper.getuniqueclassdef(C2)
@@ -1180,9 +1187,9 @@
 
         a = self.RPythonAnnotator()
         s = a.build_types(f, [int, int])
-       
+
         executedesc = a.bookkeeper.getdesc(I.execute.im_func)
-        assert len(executedesc._cache) == 2       
+        assert len(executedesc._cache) == 2
 
         assert len(executedesc._cache[(0, 'star', 2)].startblock.inputargs) == 4
         assert len(executedesc._cache[(1, 'star', 3)].startblock.inputargs) == 5
@@ -1201,7 +1208,7 @@
         s_item = listitem(s)
         assert isinstance(s_item, annmodel.SomeInstance)
         assert s_item.classdef is a.bookkeeper.getuniqueclassdef(T)
-          
+
     def test_assert_type_is_list_doesnt_lose_info(self):
         class T(object):
             pass
@@ -1254,7 +1261,7 @@
             x = bool(l)
             l.append(1)
             return x, bool(l)
-        
+
         a = self.RPythonAnnotator()
         s = a.build_types(f, [])
         assert s.const == False
@@ -1264,7 +1271,7 @@
 
         assert s.items[0].knowntype == bool and not s.items[0].is_constant()
         assert s.items[1].knowntype == bool and not s.items[1].is_constant()
-        
+
     def test_empty_dict(self):
         def f():
             d = {}
@@ -1274,7 +1281,7 @@
             x = bool(d)
             d['a'] = 1
             return x, bool(d)
-        
+
         a = self.RPythonAnnotator()
         s = a.build_types(f, [])
         assert s.const == False
@@ -1534,7 +1541,7 @@
         def witness1(x):
             pass
         def witness2(x):
-            pass        
+            pass
         def f(x):
             if 0 < x:
                 witness1(x)
@@ -1543,15 +1550,15 @@
         a = self.RPythonAnnotator()
         s = a.build_types(f, [annmodel.SomeInteger(unsigned=True)])
         wg1 = graphof(a, witness1)
-        wg2 = graphof(a, witness2)        
+        wg2 = graphof(a, witness2)
         assert a.binding(wg1.getargs()[0]).unsigned is True
-        assert a.binding(wg2.getargs()[0]).unsigned is True        
-        
+        assert a.binding(wg2.getargs()[0]).unsigned is True
+
     def test_general_nonneg_cleverness_is_gentle_with_unsigned(self):
         def witness1(x):
             pass
         def witness2(x):
-            pass        
+            pass
         def f(x):
             if 0 < x:
                 witness1(x)
@@ -1560,7 +1567,7 @@
         a = self.RPythonAnnotator()
         s = a.build_types(f, [annmodel.SomeInteger(knowntype=r_ulonglong)])
         wg1 = graphof(a, witness1)
-        wg2 = graphof(a, witness2)        
+        wg2 = graphof(a, witness2)
         assert a.binding(wg1.getargs()[0]).knowntype is r_ulonglong
         assert a.binding(wg2.getargs()[0]).knowntype is r_ulonglong
 
@@ -1742,11 +1749,11 @@
         assert s.const == "bool"
         a = self.RPythonAnnotator()
         s = a.build_types(f, [int])
-        assert s.const == "int"        
+        assert s.const == "int"
         a = self.RPythonAnnotator()
         s = a.build_types(f, [float])
-        assert s.const == "dontknow"        
-        
+        assert s.const == "dontknow"
+
     def test_hidden_method(self):
         class Base:
             def method(self):
@@ -1825,7 +1832,7 @@
         s = a.build_types(f, [])
         assert s.knowntype == bool
         assert not s.is_constant()
-            
+
     def test_const_dict_and_none(self):
         def g(d=None):
             return d is None
@@ -1837,7 +1844,7 @@
         s = a.build_types(f, [])
         assert s.knowntype == bool
         assert not s.is_constant()
-                        
+
     def test_issubtype_and_const(self):
         class A(object):
             pass
@@ -1951,7 +1958,7 @@
         a = annrpython.RPythonAnnotator()
         from pypy.annotation import model as annmodel
 
-        s_f = a.bookkeeper.immutablevalue(f) 
+        s_f = a.bookkeeper.immutablevalue(f)
         a.bookkeeper.emulate_pbc_call('f', s_f, [annmodel.SomeInteger(), annmodel.SomeInteger()])
         a.complete()
 
@@ -1960,7 +1967,7 @@
 
         someint = annmodel.SomeInteger()
 
-        assert (fdesc.get_s_signatures((2,(),False,False)) 
+        assert (fdesc.get_s_signatures((2,(),False,False))
                 == [([someint,someint],someint)])
 
     def test_emulated_pbc_call_callback(self):
@@ -1974,7 +1981,7 @@
         def callb(ann, graph):
             memo.append(annmodel.SomeInteger() == ann.binding(graph.getreturnvar()))
 
-        s_f = a.bookkeeper.immutablevalue(f) 
+        s_f = a.bookkeeper.immutablevalue(f)
         s = a.bookkeeper.emulate_pbc_call('f', s_f, [annmodel.SomeInteger(), annmodel.SomeInteger()],
                                           callback=callb)
         assert s == annmodel.SomeImpossibleValue()
@@ -1996,7 +2003,7 @@
         s = a.build_types(f, [])
         assert isinstance(s, annmodel.SomeIterator)
         assert s.variant == ('items',)
-        
+
     def test_non_none_and_none_with_isinstance(self):
         class A(object):
             pass
@@ -2230,7 +2237,7 @@
         def f(i):
             witness(None)
             return witness(get(i))
-            
+
         a = self.RPythonAnnotator()
         s = a.build_types(f, [int])
         assert s.__class__ == annmodel.SomeObject
@@ -2284,8 +2291,8 @@
         a = self.RPythonAnnotator()
         s = a.build_types(f, [])
         assert isinstance(s.items[0], annmodel.SomeInteger)
-        assert isinstance(s.items[1], annmodel.SomeChar)        
-        assert isinstance(s.items[2], annmodel.SomeChar)        
+        assert isinstance(s.items[1], annmodel.SomeChar)
+        assert isinstance(s.items[2], annmodel.SomeChar)
 
     def test___class___attribute(self):
         class Base(object): pass
@@ -2344,7 +2351,7 @@
         a = self.RPythonAnnotator()
         s = a.build_types(f, [bool])
         assert s.knowntype == int
-        
+
 
         def f(x):
             return -x
@@ -2394,7 +2401,7 @@
             assert isinstance(s, annmodel.SomeInteger)
             assert s.knowntype == inttype
             assert s.unsigned == (inttype(-1) > 0)
-            
+
         for inttype in inttypes:
             def f():
                 return inttype(0)
@@ -2493,11 +2500,11 @@
     def test_helper_method_annotator(self):
         def fun():
             return 21
-        
+
         class A(object):
             def helper(self):
                 return 42
-        
+
         a = self.RPythonAnnotator()
         a.build_types(fun, [])
         a.annotate_helper_method(A, "helper", [])
@@ -2794,7 +2801,7 @@
 
         def c(x):
             return int(x)
-        
+
         def g(a, x):
             if x == -1:
                 a = None
@@ -2806,7 +2813,7 @@
                 x = x + .01
             return a(x)
 
-        #def fun(x):   
+        #def fun(x):
 
         a = self.RPythonAnnotator(policy=policy.AnnotatorPolicy())
         s = a.build_types(g, [annmodel.SomeGenericCallable(
@@ -2845,7 +2852,7 @@
         class B(A):
             def meth(self):
                 return self
-        class C(A): 
+        class C(A):
             def meth(self):
                 return self
 
@@ -2893,7 +2900,7 @@
             i.x = x
 
         a = self.RPythonAnnotator()
-        py.test.raises(Exception, a.build_types, f, [])        
+        py.test.raises(Exception, a.build_types, f, [])
 
 
         class M:
@@ -2910,30 +2917,30 @@
                 self.l2 = []
 
         c = C()
-         
+
         def f():
             x = A()
             x = hint(x, access_directly=True)
             c.m.l.append(x)
 
         a = self.RPythonAnnotator()
-        py.test.raises(AssertionError, a.build_types, f, [])        
+        py.test.raises(AssertionError, a.build_types, f, [])
 
         def f():
             x = A()
             x = hint(x, access_directly=True)
             c.m.d[None] = x
-            
+
         a = self.RPythonAnnotator()
-        py.test.raises(AssertionError, a.build_types, f, [])        
+        py.test.raises(AssertionError, a.build_types, f, [])
 
         def f():
             x = A()
             x = hint(x, access_directly=True)
             c.m.d[x] = None
-            
+
         a = self.RPythonAnnotator()
-        py.test.raises(AssertionError, a.build_types, f, [])        
+        py.test.raises(AssertionError, a.build_types, f, [])
 
     def test_ctr_location(self):
         from pypy.rlib.jit import hint
@@ -3026,7 +3033,7 @@
 
         a = self.RPythonAnnotator()
         s = a.build_types(f, [])
-        assert isinstance(s, annmodel.SomeUnicodeString)        
+        assert isinstance(s, annmodel.SomeUnicodeString)
 
     def test_unicode(self):
         def g(n):
@@ -3091,7 +3098,7 @@
         a = self.RPythonAnnotator()
         s = a.build_types(f, [str])
         assert isinstance(s, annmodel.SomeString)
-        
+
         def f(x):
             return u'a'.replace(x, u'b')
 
@@ -3105,7 +3112,7 @@
                 if c == i:
                     return c
             return 'x'
-            
+
         a = self.RPythonAnnotator()
         s = a.build_types(f, [unicode, str])
         assert isinstance(s, annmodel.SomeUnicodeCodePoint)
@@ -3113,22 +3120,22 @@
     def test_strformatting_unicode(self):
         def f(x):
             return '%s' % unichr(x)
-            
+
         a = self.RPythonAnnotator()
         py.test.raises(NotImplementedError, a.build_types, f, [int])
         def f(x):
             return '%s' % (unichr(x) * 3)
-            
+
         a = self.RPythonAnnotator()
         py.test.raises(NotImplementedError, a.build_types, f, [int])
         def f(x):
             return '%s%s' % (1, unichr(x))
-            
+
         a = self.RPythonAnnotator()
         py.test.raises(NotImplementedError, a.build_types, f, [int])
         def f(x):
             return '%s%s' % (1, unichr(x) * 15)
-            
+
         a = self.RPythonAnnotator()
         py.test.raises(NotImplementedError, a.build_types, f, [int])
 
@@ -3197,7 +3204,7 @@
             called.append(True)
             assert not ann.listdef.listitem.mutated
             ann.listdef.never_resize()
-        
+
         def f():
             l = [1,2,3]
             check_annotation(l, checker)
@@ -3213,7 +3220,7 @@
 
     def test_listitem_no_mutating2(self):
         from pypy.rlib.debug import make_sure_not_resized
-        
+
         def f():
             return make_sure_not_resized([1,2,3])
 
@@ -3293,11 +3300,11 @@
                     return d1[x].meth()
                 d1[i+1] = A()
             return 0
-                
+
         a = self.RPythonAnnotator()
         s = a.build_types(g, [int, int])
         assert s.knowntype is int
-        
+
         def f(x):
             d0 = {}
             if x in d0:
@@ -3476,7 +3483,7 @@
     return total
 
 constant_unsigned_five = r_uint(5)
-        
+
 class Freezing:
     def _freeze_(self):
         return True
diff --git a/pypy/interpreter/astcompiler/assemble.py b/pypy/interpreter/astcompiler/assemble.py
--- a/pypy/interpreter/astcompiler/assemble.py
+++ b/pypy/interpreter/astcompiler/assemble.py
@@ -286,6 +286,7 @@
         while True:
             extended_arg_count = 0
             offset = 0
+            force_redo = False
             # Calculate the code offset of each block.
             for block in blocks:
                 block.offset = offset
@@ -313,7 +314,7 @@
                                     instr.has_jump = False
                                     # The size of the code changed,
                                     # we have to trigger another pass
-                                    extended_arg_count += 1
+                                    force_redo = True
                                     continue
                         if absolute:
                             jump_arg = target.offset
@@ -322,7 +323,7 @@
                         instr.arg = jump_arg
                         if jump_arg > 0xFFFF:
                             extended_arg_count += 1
-            if extended_arg_count == last_extended_arg_count:
+            if extended_arg_count == last_extended_arg_count and not force_redo:
                 break
             else:
                 last_extended_arg_count = extended_arg_count
diff --git a/pypy/interpreter/astcompiler/test/test_compiler.py b/pypy/interpreter/astcompiler/test/test_compiler.py
--- a/pypy/interpreter/astcompiler/test/test_compiler.py
+++ b/pypy/interpreter/astcompiler/test/test_compiler.py
@@ -73,6 +73,10 @@
     def error_test(self, source, exc_type):
         py.test.raises(exc_type, self.simple_test, source, None, None)
 
+    def test_issue_713(self):
+        func = "def f(_=2): return (_ if _ else _) if False else _"
+        yield self.st, func, "f()", 2
+
     def test_long_jump(self):
         func = """def f(x):
     y = 0
diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py
--- a/pypy/interpreter/pyopcode.py
+++ b/pypy/interpreter/pyopcode.py
@@ -1417,13 +1417,16 @@
     def print_item_to(x, stream):
         if file_softspace(stream, False):
            stream.write(" ")
-        if isinstance(x, unicode) and getattr(stream, "encoding", None) is not None:
-            x = x.encode(stream.encoding, getattr(stream, "errors", None) or "strict")
-        stream.write(str(x))
+
+        # give to write() an argument which is either a string or a unicode
+        # (and let it deals itself with unicode handling)
+        if not isinstance(x, unicode):
+            x = str(x)
+        stream.write(x)
 
         # add a softspace unless we just printed a string which ends in a '\t'
         # or '\n' -- or more generally any whitespace character but ' '
-        if isinstance(x, (str, unicode)) and x:
+        if x:
             lastchar = x[-1]
             if lastchar.isspace() and lastchar != ' ':
                 return
diff --git a/pypy/interpreter/test/test_interpreter.py b/pypy/interpreter/test/test_interpreter.py
--- a/pypy/interpreter/test/test_interpreter.py
+++ b/pypy/interpreter/test/test_interpreter.py
@@ -277,20 +277,25 @@
         class Out(object):
             def __init__(self):
                 self.data = []
-
             def write(self, x):
-                self.data.append(x)
+                self.data.append((type(x), x))
         sys.stdout = out = Out()
         try:
-            raises(UnicodeError, "print unichr(0xa2)")
-            assert out.data == []
-            out.encoding = "cp424"
             print unichr(0xa2)
-            assert out.data == [unichr(0xa2).encode("cp424"), "\n"]
+            assert out.data == [(unicode, unichr(0xa2)), (str, "\n")]
+            out.data = []
+            out.encoding = "cp424"     # ignored!
+            print unichr(0xa2)
+            assert out.data == [(unicode, unichr(0xa2)), (str, "\n")]
             del out.data[:]
             del out.encoding
             print u"foo\t", u"bar\n", u"trick", u"baz\n"  # softspace handling
-            assert out.data == ["foo\t", "bar\n", "trick", " ", "baz\n", "\n"]
+            assert out.data == [(unicode, "foo\t"),
+                                (unicode, "bar\n"),
+                                (unicode, "trick"),
+                                (str, " "),
+                                (unicode, "baz\n"),
+                                (str, "\n")]
         finally:
             sys.stdout = save
 
diff --git a/pypy/jit/backend/llsupport/descr.py b/pypy/jit/backend/llsupport/descr.py
--- a/pypy/jit/backend/llsupport/descr.py
+++ b/pypy/jit/backend/llsupport/descr.py
@@ -261,6 +261,19 @@
         self.arg_classes = arg_classes    # string of "r" and "i" (ref/int)
         self.extrainfo = extrainfo
 
+    def __repr__(self):
+        res = '%s(%s)' % (self.__class__.__name__, self.arg_classes)
+        oopspecindex = getattr(self.extrainfo, 'oopspecindex', 0)
+        if oopspecindex:
+            from pypy.jit.codewriter.effectinfo import EffectInfo
+            for key, value in EffectInfo.__dict__.items():
+                if key.startswith('OS_') and value == oopspecindex:
+                    break
+            else:
+                key = 'oopspecindex=%r' % oopspecindex
+            res += ' ' + key
+        return '<%s>' % res
+
     def get_extra_info(self):
         return self.extrainfo
 
diff --git a/pypy/jit/backend/x86/assembler.py b/pypy/jit/backend/x86/assembler.py
--- a/pypy/jit/backend/x86/assembler.py
+++ b/pypy/jit/backend/x86/assembler.py
@@ -832,6 +832,11 @@
         effectinfo = op.getdescr().get_extra_info()
         oopspecindex = effectinfo.oopspecindex
         genop_llong_list[oopspecindex](self, op, arglocs, resloc)
+        
+    def regalloc_perform_math(self, op, arglocs, resloc):
+        effectinfo = op.getdescr().get_extra_info()
+        oopspecindex = effectinfo.oopspecindex
+        genop_math_list[oopspecindex](self, op, arglocs, resloc)
 
     def regalloc_perform_with_guard(self, op, guard_op, faillocs,
                                     arglocs, resloc, current_depths):
@@ -1119,6 +1124,9 @@
     genop_guard_float_eq = _cmpop_guard_float("E", "E", "NE","NE")
     genop_guard_float_gt = _cmpop_guard_float("A", "B", "BE","AE")
     genop_guard_float_ge = _cmpop_guard_float("AE","BE", "B", "A")
+    
+    def genop_math_sqrt(self, op, arglocs, resloc):
+        self.mc.SQRTSD(arglocs[0], resloc)
 
     def genop_guard_float_ne(self, op, guard_op, guard_token, arglocs, result_loc):
         guard_opnum = guard_op.getopnum()
@@ -2158,6 +2166,7 @@
 genop_discard_list = [Assembler386.not_implemented_op_discard] * rop._LAST
 genop_list = [Assembler386.not_implemented_op] * rop._LAST
 genop_llong_list = {}
+genop_math_list = {}
 genop_guard_list = [Assembler386.not_implemented_op_guard] * rop._LAST
 
 for name, value in Assembler386.__dict__.iteritems():
@@ -2173,6 +2182,10 @@
         opname = name[len('genop_llong_'):]
         num = getattr(EffectInfo, 'OS_LLONG_' + opname.upper())
         genop_llong_list[num] = value
+    elif name.startswith('genop_math_'):
+        opname = name[len('genop_math_'):]
+        num = getattr(EffectInfo, 'OS_MATH_' + opname.upper())
+        genop_math_list[num] = value
     elif name.startswith('genop_'):
         opname = name[len('genop_'):]
         num = getattr(rop, opname.upper())
diff --git a/pypy/jit/backend/x86/regalloc.py b/pypy/jit/backend/x86/regalloc.py
--- a/pypy/jit/backend/x86/regalloc.py
+++ b/pypy/jit/backend/x86/regalloc.py
@@ -324,6 +324,11 @@
         if not we_are_translated():
             self.assembler.dump('%s <- %s(%s)' % (result_loc, op, arglocs))
         self.assembler.regalloc_perform_llong(op, arglocs, result_loc)
+        
+    def PerformMath(self, op, arglocs, result_loc):
+        if not we_are_translated():
+            self.assembler.dump('%s <- %s(%s)' % (result_loc, op, arglocs))
+        self.assembler.regalloc_perform_math(op, arglocs, result_loc)
 
     def locs_for_fail(self, guard_op):
         return [self.loc(v) for v in guard_op.getfailargs()]
@@ -619,15 +624,13 @@
     consider_float_gt = _consider_float_cmp
     consider_float_ge = _consider_float_cmp
 
-    def consider_float_neg(self, op):
+    def _consider_float_unary_op(self, op):
         loc0 = self.xrm.force_result_in_reg(op.result, op.getarg(0))
         self.Perform(op, [loc0], loc0)
         self.xrm.possibly_free_var(op.getarg(0))
-
-    def consider_float_abs(self, op):
-        loc0 = self.xrm.force_result_in_reg(op.result, op.getarg(0))
-        self.Perform(op, [loc0], loc0)
-        self.xrm.possibly_free_var(op.getarg(0))
+        
+    consider_float_neg = _consider_float_unary_op
+    consider_float_abs = _consider_float_unary_op
 
     def consider_cast_float_to_int(self, op):
         loc0 = self.xrm.make_sure_var_in_reg(op.getarg(0))
@@ -713,6 +716,11 @@
         loc1 = self.rm.make_sure_var_in_reg(op.getarg(1))
         self.PerformLLong(op, [loc1], loc0)
         self.rm.possibly_free_vars_for_op(op)
+        
+    def _consider_math_sqrt(self, op):
+        loc0 = self.xrm.force_result_in_reg(op.result, op.getarg(1))
+        self.PerformMath(op, [loc0], loc0)
+        self.xrm.possibly_free_var(op.getarg(1))
 
     def _call(self, op, arglocs, force_store=[], guard_not_forced_op=None):
         save_all_regs = guard_not_forced_op is not None
@@ -749,12 +757,12 @@
                    guard_not_forced_op=guard_not_forced_op)
 
     def consider_call(self, op):
-        if IS_X86_32:
-            # support for some of the llong operations,
-            # which only exist on x86-32
-            effectinfo = op.getdescr().get_extra_info()
-            if effectinfo is not None:
-                oopspecindex = effectinfo.oopspecindex
+        effectinfo = op.getdescr().get_extra_info()
+        if effectinfo is not None:
+            oopspecindex = effectinfo.oopspecindex
+            if IS_X86_32:
+                # support for some of the llong operations,
+                # which only exist on x86-32
                 if oopspecindex in (EffectInfo.OS_LLONG_ADD,
                                     EffectInfo.OS_LLONG_SUB,
                                     EffectInfo.OS_LLONG_AND,
@@ -773,7 +781,8 @@
                 if oopspecindex == EffectInfo.OS_LLONG_LT:
                     if self._maybe_consider_llong_lt(op):
                         return
-        #
+            if oopspecindex == EffectInfo.OS_MATH_SQRT:
+                return self._consider_math_sqrt(op)
         self._consider_call(op)
 
     def consider_call_may_force(self, op, guard_op):
diff --git a/pypy/jit/backend/x86/regloc.py b/pypy/jit/backend/x86/regloc.py
--- a/pypy/jit/backend/x86/regloc.py
+++ b/pypy/jit/backend/x86/regloc.py
@@ -515,6 +515,8 @@
     UCOMISD = _binaryop('UCOMISD')
     CVTSI2SD = _binaryop('CVTSI2SD')
     CVTTSD2SI = _binaryop('CVTTSD2SI')
+    
+    SQRTSD = _binaryop('SQRTSD')
 
     ANDPD = _binaryop('ANDPD')
     XORPD = _binaryop('XORPD')
diff --git a/pypy/jit/backend/x86/runner.py b/pypy/jit/backend/x86/runner.py
--- a/pypy/jit/backend/x86/runner.py
+++ b/pypy/jit/backend/x86/runner.py
@@ -1,3 +1,4 @@
+import py
 from pypy.rpython.lltypesystem import lltype, llmemory, rffi
 from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.rpython.llinterp import LLInterpreter
@@ -10,6 +11,11 @@
 from pypy.jit.backend.x86 import regloc
 import sys
 
+from pypy.tool.ansi_print import ansi_log
+log = py.log.Producer('jitbackend')
+py.log.setconsumer('jitbackend', ansi_log)
+
+
 class AbstractX86CPU(AbstractLLCPU):
     debug = True
     supports_floats = True
@@ -29,6 +35,8 @@
             config = rtyper.annotator.translator.config
             if config.translation.jit_profiler == "oprofile":
                 from pypy.jit.backend.x86 import oprofile
+                if not oprofile.OPROFILE_AVAILABLE:
+                    log.WARNING('oprofile support was explicitly enabled, but oprofile headers seem not to be available')
                 profile_agent = oprofile.OProfileAgent()
 
         self.profile_agent = profile_agent
diff --git a/pypy/jit/backend/x86/rx86.py b/pypy/jit/backend/x86/rx86.py
--- a/pypy/jit/backend/x86/rx86.py
+++ b/pypy/jit/backend/x86/rx86.py
@@ -691,6 +691,8 @@
 define_modrm_modes('MOVSD_x*', ['\xF2', rex_nw, '\x0F\x10', register(1,8)], regtype='XMM')
 define_modrm_modes('MOVSD_*x', ['\xF2', rex_nw, '\x0F\x11', register(2,8)], regtype='XMM')
 
+define_modrm_modes('SQRTSD_x*', ['\xF2', rex_nw, '\x0F\x51', register(1,8)], regtype='XMM')
+
 #define_modrm_modes('XCHG_r*', [rex_w, '\x87', register(1, 8)])
 
 define_modrm_modes('ADDSD_x*', ['\xF2', rex_nw, '\x0F\x58', register(1, 8)], regtype='XMM')
diff --git a/pypy/jit/codewriter/effectinfo.py b/pypy/jit/codewriter/effectinfo.py
--- a/pypy/jit/codewriter/effectinfo.py
+++ b/pypy/jit/codewriter/effectinfo.py
@@ -72,6 +72,8 @@
     OS_LLONG_UGE                = 91
     OS_LLONG_URSHIFT            = 92
     OS_LLONG_FROM_UINT          = 93
+    #
+    OS_MATH_SQRT                = 100
 
     def __new__(cls, readonly_descrs_fields,
                 write_descrs_fields, write_descrs_arrays,
diff --git a/pypy/jit/codewriter/jtransform.py b/pypy/jit/codewriter/jtransform.py
--- a/pypy/jit/codewriter/jtransform.py
+++ b/pypy/jit/codewriter/jtransform.py
@@ -351,6 +351,8 @@
             prepare = self._handle_jit_call
         elif oopspec_name.startswith('libffi_'):
             prepare = self._handle_libffi_call
+        elif oopspec_name.startswith('math.sqrt'):
+            prepare = self._handle_math_sqrt_call
         else:
             prepare = self.prepare_builtin_call
         try:
@@ -1360,6 +1362,13 @@
         assert vinfo is not None
         self.vable_flags[op.args[0]] = op.args[2].value
         return []
+        
+    # ---------
+    # ll_math.sqrt_nonneg()
+    
+    def _handle_math_sqrt_call(self, op, oopspec_name, args):
+        return self._handle_oopspec_call(op, args, EffectInfo.OS_MATH_SQRT,
+                                         EffectInfo.EF_PURE)
 
 # ____________________________________________________________
 
diff --git a/pypy/jit/codewriter/support.py b/pypy/jit/codewriter/support.py
--- a/pypy/jit/codewriter/support.py
+++ b/pypy/jit/codewriter/support.py
@@ -4,6 +4,7 @@
 from pypy.rpython import rlist
 from pypy.rpython.lltypesystem import rstr as ll_rstr, rdict as ll_rdict
 from pypy.rpython.lltypesystem import rlist as lltypesystem_rlist
+from pypy.rpython.lltypesystem.module import ll_math
 from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.rpython.ootypesystem import rdict as oo_rdict
 from pypy.rpython.llinterp import LLInterpreter
@@ -221,6 +222,11 @@
         return -x
     else:
         return x
+        
+# math support
+# ------------
+
+_ll_1_ll_math_ll_math_sqrt = ll_math.ll_math_sqrt
 
 
 # long long support
@@ -388,6 +394,7 @@
     ('int_mod_zer',          [lltype.Signed, lltype.Signed], lltype.Signed),
     ('int_lshift_ovf',       [lltype.Signed, lltype.Signed], lltype.Signed),
     ('int_abs',              [lltype.Signed],                lltype.Signed),
+    ('ll_math.ll_math_sqrt', [lltype.Float],                 lltype.Float),
     ]
 
 
diff --git a/pypy/jit/codewriter/test/test_jtransform.py b/pypy/jit/codewriter/test/test_jtransform.py
--- a/pypy/jit/codewriter/test/test_jtransform.py
+++ b/pypy/jit/codewriter/test/test_jtransform.py
@@ -5,6 +5,7 @@
 from pypy.jit.codewriter.jtransform import Transformer
 from pypy.jit.metainterp.history import getkind
 from pypy.rpython.lltypesystem import lltype, llmemory, rclass, rstr, rlist
+from pypy.rpython.lltypesystem.module import ll_math
 from pypy.translator.unsimplify import varoftype
 from pypy.jit.codewriter import heaptracker, effectinfo
 from pypy.jit.codewriter.flatten import ListOfKind
@@ -98,7 +99,9 @@
             PUNICODE = lltype.Ptr(rstr.UNICODE)
             INT = lltype.Signed
             UNICHAR = lltype.UniChar
+            FLOAT = lltype.Float
             argtypes = {
+             EI.OS_MATH_SQRT:  ([FLOAT], FLOAT),
              EI.OS_STR2UNICODE:([PSTR], PUNICODE),
              EI.OS_STR_CONCAT: ([PSTR, PSTR], PSTR),
              EI.OS_STR_SLICE:  ([PSTR, INT, INT], PSTR),
@@ -947,3 +950,22 @@
     assert op1.args[1] == 'calldescr-%d' % effectinfo.EffectInfo.OS_ARRAYCOPY
     assert op1.args[2] == ListOfKind('int', [v3, v4, v5])
     assert op1.args[3] == ListOfKind('ref', [v1, v2])
+
+def test_math_sqrt():
+    # test that the oopspec is present and correctly transformed
+    FLOAT = lltype.Float
+    FUNC = lltype.FuncType([FLOAT], FLOAT)
+    func = lltype.functionptr(FUNC, 'll_math',
+                              _callable=ll_math.sqrt_nonneg)
+    v1 = varoftype(FLOAT)
+    v2 = varoftype(FLOAT)
+    op = SpaceOperation('direct_call', [const(func), v1], v2)
+    tr = Transformer(FakeCPU(), FakeBuiltinCallControl())
+    op1 = tr.rewrite_operation(op)
+    assert op1.opname == 'residual_call_irf_f'
+    assert op1.args[0].value == func
+    assert op1.args[1] == 'calldescr-%d' % effectinfo.EffectInfo.OS_MATH_SQRT
+    assert op1.args[2] == ListOfKind("int", [])
+    assert op1.args[3] == ListOfKind("ref", [])
+    assert op1.args[4] == ListOfKind('float', [v1])
+    assert op1.result == v2
diff --git a/pypy/jit/metainterp/test/support.py b/pypy/jit/metainterp/test/support.py
--- a/pypy/jit/metainterp/test/support.py
+++ b/pypy/jit/metainterp/test/support.py
@@ -9,6 +9,7 @@
 from pypy.jit.metainterp.warmstate import set_future_value
 from pypy.jit.codewriter.policy import JitPolicy
 from pypy.jit.codewriter import longlong
+from pypy.rlib.rfloat import isinf, isnan
 
 def _get_jitcodes(testself, CPUClass, func, values, type_system,
                   supports_longlong=False, **kwds):
@@ -51,6 +52,7 @@
     cw = codewriter.CodeWriter(cpu, [FakeJitDriverSD()])
     testself.cw = cw
     policy = JitPolicy()
+    policy.set_supports_floats(True)
     policy.set_supports_longlong(supports_longlong)
     cw.find_all_graphs(policy)
     #
@@ -180,10 +182,10 @@
         result1 = _run_with_blackhole(self, args)
         # try to run it with pyjitpl.py
         result2 = _run_with_pyjitpl(self, args)
-        assert result1 == result2
+        assert result1 == result2 or isnan(result1) and isnan(result2)
         # try to run it by running the code compiled just before
         result3 = _run_with_machine_code(self, args)
-        assert result1 == result3 or result3 == NotImplemented
+        assert result1 == result3 or result3 == NotImplemented or isnan(result1) and isnan(result3)
         #
         if (longlong.supports_longlong and
             isinstance(result1, longlong.r_float_storage)):
diff --git a/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py b/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
--- a/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
@@ -1664,6 +1664,7 @@
         assert loop.match_by_id('shift', "")  # optimized away
 
     def test_division_to_rshift(self):
+        py.test.skip('in-progress')
         def main(b):
             res = 0
             a = 0
diff --git a/pypy/objspace/std/stringobject.py b/pypy/objspace/std/stringobject.py
--- a/pypy/objspace/std/stringobject.py
+++ b/pypy/objspace/std/stringobject.py
@@ -11,7 +11,7 @@
 from pypy.objspace.std.listobject import W_ListObject
 from pypy.objspace.std.noneobject import W_NoneObject
 from pypy.objspace.std.tupleobject import W_TupleObject
-from pypy.rlib.rstring import StringBuilder, string_repeat
+from pypy.rlib.rstring import StringBuilder
 from pypy.interpreter.buffer import StringBuffer
 
 from pypy.objspace.std.stringtype import sliced, wrapstr, wrapchar, \
@@ -856,7 +856,7 @@
     if len(input) == 1:
         s = input[0] * mul
     else:
-        s = string_repeat(input, mul)
+        s = input * mul
     # xxx support again space.config.objspace.std.withstrjoin?
     return W_StringObject(s)
 
@@ -963,19 +963,20 @@
                 space.wrap("translation table must be 256 characters long"))
 
     string = w_string._value
-    chars = []
     deletechars = space.str_w(w_deletechars)
     if len(deletechars) == 0:
+        buf = StringBuilder(len(string))
         for char in string:
-            chars.append(table[ord(char)])
+            buf.append(table[ord(char)])
     else:
+        buf = StringBuilder()
         deletion_table = [False] * 256
         for c in deletechars:
             deletion_table[ord(c)] = True
         for char in string:
             if not deletion_table[ord(char)]:
-                chars.append(table[ord(char)])
-    return W_StringObject(''.join(chars))
+                buf.append(table[ord(char)])
+    return W_StringObject(buf.build())
 
 def str_decode__String_ANY_ANY(space, w_string, w_encoding=None, w_errors=None):
     from pypy.objspace.std.unicodetype import _get_encoding_and_errors, \
diff --git a/pypy/objspace/std/unicodeobject.py b/pypy/objspace/std/unicodeobject.py
--- a/pypy/objspace/std/unicodeobject.py
+++ b/pypy/objspace/std/unicodeobject.py
@@ -11,7 +11,7 @@
 from pypy.objspace.std.tupleobject import W_TupleObject
 from pypy.rlib.rarithmetic import intmask, ovfcheck
 from pypy.rlib.objectmodel import compute_hash
-from pypy.rlib.rstring import UnicodeBuilder, string_repeat
+from pypy.rlib.rstring import UnicodeBuilder
 from pypy.rlib.runicode import unicode_encode_unicode_escape
 from pypy.module.unicodedata import unicodedb
 from pypy.tool.sourcetools import func_with_new_name
@@ -278,7 +278,7 @@
     if len(input) == 1:
         result = input[0] * times
     else:
-        result = string_repeat(input, times)
+        result = input * times
     return W_UnicodeObject(result)
 
 def mul__ANY_Unicode(space, w_times, w_uni):
diff --git a/pypy/rlib/rstring.py b/pypy/rlib/rstring.py
--- a/pypy/rlib/rstring.py
+++ b/pypy/rlib/rstring.py
@@ -3,7 +3,6 @@
 
 from pypy.annotation.model import SomeObject, SomeString, s_None,\
      SomeChar, SomeInteger, SomeUnicodeCodePoint, SomeUnicodeString
-from pypy.rlib.rarithmetic import ovfcheck
 from pypy.rpython.extregistry import ExtRegistryEntry
 
 
@@ -79,32 +78,6 @@
     tp = unicode
 
 
-# XXX: This does log(mul) mallocs, the GCs probably make that efficient, but
-# some measurement should be done at some point.
-def string_repeat(s, mul):
-    """Repeat a string or unicode.  Note that this assumes that 'mul' > 0."""
-    result = None
-    factor = 1
-    assert mul > 0
-    try:
-        ovfcheck(len(s) * mul)
-    except OverflowError:
-        raise MemoryError
-    
-    limit = mul >> 1
-    while True:
-        if mul & factor:
-            if result is None:
-                result = s
-            else:
-                result = s + result
-            if factor > limit:
-                break
-        s += s
-        factor *= 2
-    return result
-string_repeat._annspecialcase_ = 'specialize:argtype(0)'
-
 # ------------------------------------------------------------
 # ----------------- implementation details -------------------
 # ------------------------------------------------------------
@@ -159,7 +132,7 @@
 
     def method_build(self):
         return SomeUnicodeString()
-    
+
     def rtyper_makerepr(self, rtyper):
         return rtyper.type_system.rbuilder.unicodebuilder_repr
 
@@ -170,7 +143,7 @@
         if self.use_unicode:
             return SomeUnicodeBuilder()
         return SomeStringBuilder()
-    
+
     def specialize_call(self, hop):
         return hop.r_result.rtyper_new(hop)
 
diff --git a/pypy/rlib/test/test_rstring.py b/pypy/rlib/test/test_rstring.py
--- a/pypy/rlib/test/test_rstring.py
+++ b/pypy/rlib/test/test_rstring.py
@@ -1,7 +1,6 @@
 import sys
 
-from pypy.rlib.rstring import StringBuilder, UnicodeBuilder, split, rsplit, \
-    string_repeat
+from pypy.rlib.rstring import StringBuilder, UnicodeBuilder, split, rsplit
 
 
 def test_split():
@@ -43,7 +42,4 @@
     assert s.getlength() == len('aabcb')
     s.append_multiple_char(u'd', 4)
     assert s.build() == 'aabcbdddd'
-    assert isinstance(s.build(), unicode)
-
-def test_string_repeat():
-    raises(MemoryError, string_repeat, "abc", sys.maxint)
+    assert isinstance(s.build(), unicode)
\ No newline at end of file
diff --git a/pypy/rpython/extfuncregistry.py b/pypy/rpython/extfuncregistry.py
--- a/pypy/rpython/extfuncregistry.py
+++ b/pypy/rpython/extfuncregistry.py
@@ -45,6 +45,9 @@
 register_external(math.floor, [float], float,
                   export_name="ll_math.ll_math_floor", sandboxsafe=True,
                   llimpl=ll_math.ll_math_floor)
+register_external(math.sqrt, [float], float,
+                  export_name="ll_math.ll_math_sqrt", sandboxsafe=True,
+                  llimpl=ll_math.ll_math_sqrt)
 
 complex_math_functions = [
     ('frexp', [float],        (float, int)),
diff --git a/pypy/rpython/lltypesystem/module/ll_math.py b/pypy/rpython/lltypesystem/module/ll_math.py
--- a/pypy/rpython/lltypesystem/module/ll_math.py
+++ b/pypy/rpython/lltypesystem/module/ll_math.py
@@ -9,7 +9,7 @@
 from pypy.rlib import jit, rposix
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 from pypy.translator.platform import platform
-from pypy.rlib.rfloat import isinf, isnan, INFINITY, NAN
+from pypy.rlib.rfloat import isfinite, isinf, isnan, INFINITY, NAN
 
 if sys.platform == "win32":
     if platform.name == "msvc":
@@ -69,6 +69,13 @@
                         [rffi.DOUBLE, rffi.DOUBLE], rffi.DOUBLE)
 math_floor = llexternal('floor', [rffi.DOUBLE], rffi.DOUBLE, pure_function=True)
 
+math_sqrt = llexternal('sqrt', [rffi.DOUBLE], rffi.DOUBLE)
+
+ at jit.purefunction
+def sqrt_nonneg(x):
+    return math_sqrt(x)
+sqrt_nonneg.oopspec = "math.sqrt_nonneg(x)"
+
 # ____________________________________________________________
 #
 # Error handling functions
@@ -319,6 +326,15 @@
         _likely_raise(errno, r)
     return r
 
+def ll_math_sqrt(x):
+    if x < 0.0:
+        raise ValueError, "math domain error"
+    
+    if isfinite(x):
+        return sqrt_nonneg(x)
+
+    return x   # +inf or nan
+
 # ____________________________________________________________
 #
 # Default implementations
@@ -357,7 +373,7 @@
 unary_math_functions = [
     'acos', 'asin', 'atan',
     'ceil', 'cos', 'cosh', 'exp', 'fabs',
-    'sin', 'sinh', 'sqrt', 'tan', 'tanh', 'log', 'log10',
+    'sin', 'sinh', 'tan', 'tanh', 'log', 'log10',
     'acosh', 'asinh', 'atanh', 'log1p', 'expm1',
     ]
 unary_math_functions_can_overflow = [
diff --git a/pypy/rpython/lltypesystem/rstr.py b/pypy/rpython/lltypesystem/rstr.py
--- a/pypy/rpython/lltypesystem/rstr.py
+++ b/pypy/rpython/lltypesystem/rstr.py
@@ -5,6 +5,7 @@
 from pypy.rlib.objectmodel import _hash_string, enforceargs
 from pypy.rlib.debug import ll_assert
 from pypy.rlib.jit import purefunction, we_are_jitted
+from pypy.rlib.rarithmetic import ovfcheck
 from pypy.rpython.robject import PyObjRepr, pyobj_repr
 from pypy.rpython.rmodel import inputconst, IntegerRepr
 from pypy.rpython.rstr import AbstractStringRepr,AbstractCharRepr,\
@@ -255,6 +256,27 @@
 
 
 class LLHelpers(AbstractLLHelpers):
+    @purefunction
+    def ll_str_mul(s, times):
+        if times < 0:
+            times = 0
+        try:
+            size = ovfcheck(len(s.chars) * times)
+        except OverflowError:
+            raise MemoryError
+        newstr = s.malloc(size)
+        i = 0
+        if i < size:
+            s.copy_contents(s, newstr, 0, 0, len(s.chars))
+            i += len(s.chars)
+        while i < size:
+            if i <= size - i:
+                j = i
+            else:
+                j = size - i
+            s.copy_contents(newstr, newstr, 0, i, j)
+            i += j
+        return newstr
 
     @purefunction
     def ll_char_mul(ch, times):
diff --git a/pypy/rpython/ootypesystem/rstr.py b/pypy/rpython/ootypesystem/rstr.py
--- a/pypy/rpython/ootypesystem/rstr.py
+++ b/pypy/rpython/ootypesystem/rstr.py
@@ -1,4 +1,5 @@
 from pypy.tool.pairtype import pairtype
+from pypy.rlib.rarithmetic import ovfcheck
 from pypy.rpython.error import TyperError
 from pypy.rpython.rstr import AbstractStringRepr,AbstractCharRepr,\
      AbstractUniCharRepr, AbstractStringIteratorRepr,\
@@ -134,6 +135,19 @@
             i+= 1
         return buf.ll_build()
 
+    def ll_str_mul(s, times):
+        if times < 0:
+            times = 0
+        try:
+            size = ovfcheck(s.ll_strlen() * times)
+        except OverflowError:
+            raise MemoryError
+        buf = ootype.new(typeOf(s).builder)
+        buf.ll_allocate(size)
+        for i in xrange(times):
+            buf.ll_append(s)
+        return buf.ll_build()
+
     def ll_streq(s1, s2):
         if s1 is None:
             return s2 is None
@@ -203,7 +217,7 @@
         return s.ll_substring(start, s.ll_strlen() - start)
 
     def ll_stringslice_startstop(s, start, stop):
-        length = s.ll_strlen()        
+        length = s.ll_strlen()
         if stop > length:
             stop = length
         return s.ll_substring(start, stop-start)
@@ -265,7 +279,7 @@
 
     def ll_float(ll_str):
         return ootype.ooparse_float(ll_str)
-    
+
     # interface to build strings:
     #   x = ll_build_start(n)
     #   ll_build_push(x, next_string, 0)
@@ -300,7 +314,7 @@
         c8 = hop.inputconst(ootype.Signed, 8)
         c10 = hop.inputconst(ootype.Signed, 10)
         c16 = hop.inputconst(ootype.Signed, 16)
-        c_StringBuilder = hop.inputconst(ootype.Void, ootype.StringBuilder)        
+        c_StringBuilder = hop.inputconst(ootype.Void, ootype.StringBuilder)
         v_buf = hop.genop("new", [c_StringBuilder], resulttype=ootype.StringBuilder)
 
         things = cls.parse_fmt_string(s)
@@ -334,7 +348,7 @@
             hop.genop('oosend', [c_append, v_buf, vchunk], resulttype=ootype.Void)
 
         hop.exception_cannot_occur()   # to ignore the ZeroDivisionError of '%'
-        return hop.genop('oosend', [c_build, v_buf], resulttype=ootype.String)        
+        return hop.genop('oosend', [c_build, v_buf], resulttype=ootype.String)
     do_stringformat = classmethod(do_stringformat)
 
 
@@ -399,7 +413,7 @@
     return iter
 
 def ll_strnext(iter):
-    string = iter.string    
+    string = iter.string
     index = iter.index
     if index >= string.ll_strlen():
         raise StopIteration
diff --git a/pypy/rpython/rstr.py b/pypy/rpython/rstr.py
--- a/pypy/rpython/rstr.py
+++ b/pypy/rpython/rstr.py
@@ -34,7 +34,7 @@
 class __extend__(annmodel.SomeUnicodeString):
     def rtyper_makerepr(self, rtyper):
         return rtyper.type_system.rstr.unicode_repr
-    
+
     def rtyper_makekey(self):
         return self.__class__,
 
@@ -164,7 +164,7 @@
         v_str, = hop.inputargs(string_repr)
         hop.exception_cannot_occur()
         return hop.gendirectcall(self.ll.ll_upper, v_str)
-        
+
     def rtype_method_lower(self, hop):
         string_repr = hop.args_r[0].repr
         v_str, = hop.inputargs(string_repr)
@@ -361,6 +361,17 @@
 
     rtype_getitem_idx_key = rtype_getitem_idx
 
+    def rtype_mul((r_str, r_int), hop):
+        str_repr = r_str.repr
+        v_str, v_int = hop.inputargs(str_repr, Signed)
+        return hop.gendirectcall(r_str.ll.ll_str_mul, v_str, v_int)
+    rtype_inplace_mul = rtype_mul
+
+class __extend__(pairtype(IntegerRepr, AbstractStringRepr)):
+    def rtype_mul((r_int, r_str), hop):
+        return pair(r_str, r_int).rtype_mul(hop)
+    rtype_inplace_mul = rtype_mul
+
 
 class __extend__(AbstractStringRepr):
 
@@ -384,7 +395,7 @@
     def rtype_eq((r_str1, r_str2), hop):
         v_str1, v_str2 = hop.inputargs(r_str1.repr, r_str2.repr)
         return hop.gendirectcall(r_str1.ll.ll_streq, v_str1, v_str2)
-    
+
     def rtype_ne((r_str1, r_str2), hop):
         v_str1, v_str2 = hop.inputargs(r_str1.repr, r_str2.repr)
         vres = hop.gendirectcall(r_str1.ll.ll_streq, v_str1, v_str2)
@@ -465,7 +476,7 @@
         return value
 
     def get_ll_eq_function(self):
-        return None 
+        return None
 
     def get_ll_hash_function(self):
         return self.ll.ll_char_hash
@@ -505,7 +516,7 @@
 
 class __extend__(pairtype(AbstractCharRepr, IntegerRepr),
                  pairtype(AbstractUniCharRepr, IntegerRepr)):
-    
+
     def rtype_mul((r_chr, r_int), hop):
         char_repr = r_chr.char_repr
         v_char, v_int = hop.inputargs(char_repr, Signed)
@@ -545,7 +556,7 @@
         return value
 
     def get_ll_eq_function(self):
-        return None 
+        return None
 
     def get_ll_hash_function(self):
         return self.ll.ll_unichar_hash
diff --git a/pypy/rpython/test/test_rstr.py b/pypy/rpython/test/test_rstr.py
--- a/pypy/rpython/test/test_rstr.py
+++ b/pypy/rpython/test/test_rstr.py
@@ -88,7 +88,7 @@
         for i in range(3):
             res = self.interpret(fn, [i])
             assert res is True
-        
+
     def test_char_constant(self):
         const = self.const
         def fn(s):
@@ -141,6 +141,16 @@
         res = self.interpret(fn, [const('5'), 3])
         assert res == 5551
 
+    def test_str_mul(self):
+        const = self.const
+        def fn(i, mul):
+            s = ["", "a", "aba"][i]
+            return s * mul
+        for i in xrange(3):
+            for m in [0, 1, 4]:
+                res = self.interpret(fn, [i, m])
+                assert self.ll_to_string(res) == fn(i, m)
+
     def test_is_none(self):
         const = self.const
         def fn(i):
@@ -295,7 +305,7 @@
         for i, expected in enumerate([0, 1110, 2220, 3330, -1110, -1110]):
             res = self.interpret(f, [i])
             assert res == expected
-            
+
     def test_rfind(self):
         const = self.const
         def fn():
@@ -531,7 +541,7 @@
         assert res.find('>, much nicer than <D object') != -1
 
         res = self.ll_to_string(self.interpret(dummy, [0]))
-        res = res.replace('pypy.rpython.test.test_rstr.', '')        
+        res = res.replace('pypy.rpython.test.test_rstr.', '')
         assert res.find('what a nice <D object') != -1
         assert res.find('>, much nicer than <C object') != -1
 
@@ -786,7 +796,7 @@
             return const('ababa').count(const('aba'))
         res = self.interpret(fn, [])
         assert res == 1
-       
+
     def test_count_TyperError(self):
         const = self.const
         def f():
@@ -797,7 +807,7 @@
             s = const('abc')
             s.count(s, -10)
         raises(TyperError, self.interpret, f, ())
-    
+
     def test_getitem_exc(self):
         const = self.const
         def f(x):
@@ -812,7 +822,7 @@
             pass
         else:
             assert False
-    
+
         def f(x):
             s = const("z")
             try:
@@ -825,7 +835,7 @@
         res = self.interpret(f, [0])
         assert res == 'z'
         res = self.interpret(f, [1])
-        assert res == 'X'        
+        assert res == 'X'
 
         def f(x):
             s = const("z")
@@ -882,7 +892,7 @@
 
         assert self.ll_to_string(self.interpret(f, [1,
                                        self.string_to_ll('abc')])) == 'ababc'
-        
+
     def test_hlstr(self):
         const = self.const
         from pypy.rpython.annlowlevel import hlstr
@@ -965,7 +975,7 @@
 
     def test_ll_find_rfind(self):
         llstr = self.string_to_ll
-        
+
         for i in range(50):
             n1 = random.randint(0, 10)
             s1 = ''.join([random.choice("ab") for i in range(n1)])
diff --git a/pypy/rpython/tool/rffi_platform.py b/pypy/rpython/tool/rffi_platform.py
--- a/pypy/rpython/tool/rffi_platform.py
+++ b/pypy/rpython/tool/rffi_platform.py
@@ -787,7 +787,7 @@
     eci = ExternalCompilationInfo(
         platform=platform,
         includes=includes,
-        libraries=['gc'],
+        libraries=['gc', 'dl'],
         )
     return configure_external_library(
         'gc', eci,
diff --git a/pypy/tool/algo/test/test_unionref.py b/pypy/tool/algo/test/test_unionref.py
deleted file mode 100644
--- a/pypy/tool/algo/test/test_unionref.py
+++ /dev/null
@@ -1,55 +0,0 @@
-from pypy.tool.algo.unionref import UnionRef, UnionDict
-
-def test_ref():
-    x = object()
-    ref = UnionRef(x)
-    assert ref() is x
-    assert ref == ref
-    assert ref != UnionRef(x)
-
-def test_merge():
-    d1 = {1: '1'}
-    d2 = {2: '2'}
-    d3 = {3: '3'}
-    d4 = {4: '4'}
-    r1 = UnionRef(d1)
-    r2 = UnionRef(d2)
-    r3 = UnionRef(d3)
-    r4 = UnionRef(d4)
-    r1.merge(r1)
-    assert r1 != r2 != r3 != r4
-    r1.merge(r2)
-    assert r1() is r2() == {1: '1', 2: '2'}
-    assert r1 == r2
-    r3.merge(r4)
-    assert r3() is r4() == {3: '3', 4: '4'}
-    assert r1 != r3
-    assert r2 != r3
-    assert r1 != r4
-    assert r2 != r4
-    r1.merge(r4)
-    assert r1() is r2() is r3() is r4() == {1: '1', 2: '2', 3: '3', 4: '4'}
-    assert r1 == r2 == r3 == r4
-
-def test_uniondict():
-    k1 = object()
-    k2 = object()
-    k3 = object()
-    k4 = object()
-    d = UnionDict()
-    d[k1] = {1: '1'}
-    d[k2] = {2: '2'}
-    d[k3] = {3: '3'}
-    d[k4] = {4: '4'}
-    assert d[k1] == {1: '1'}
-    assert d[k2] == {2: '2'}
-    assert d[k3] == {3: '3'}
-    assert d[k4] == {4: '4'}
-    assert len(d) == 4
-    d.merge(k1, k2)
-    d.merge(k3, k4)
-    assert d[k1] is d[k2] == {1: '1', 2: '2'}
-    assert d[k3] is d[k4] == {3: '3', 4: '4'}
-    d.merge(k1, k4)
-    assert d[k1] is d[k2] is d[k3] is d[k4] == {1: '1', 2: '2', 3: '3', 4: '4'}
-    assert len(d) == 4
diff --git a/pypy/tool/algo/unionref.py b/pypy/tool/algo/unionref.py
deleted file mode 100644
--- a/pypy/tool/algo/unionref.py
+++ /dev/null
@@ -1,151 +0,0 @@
-"""
-ref = UnionRef(x) -> creates a reference to x, such that ref() is x.
-
-Two references can be merged: ref.merge(ref2) make ref and ref2 interchangeable.
-After a merge, ref() is ref2().  This is done by asking the two older objects
-that ref and ref2 pointed to how they should be merged.  The point is that
-large equivalence relations can be built this way:
-
-    >>> ref1.merge(ref2)
-    >>> ref3.merge(ref4)
-    >>> ref1() is ref4()
-    False
-    >>> ref2.merge(ref3)
-    >>> ref1() is ref4()
-    True
-
-By default, two objects x and y are merged by calling x.update(y).
-"""
-
-import UserDict
-from pypy.tool.uid import uid
-
-
-class UnionRef(object):
-    __slots__ = ('_obj', '_parent', '_weight')
-
-    def __init__(self, obj):
-        "Build a new reference to 'obj'."
-        self._obj = obj
-        self._parent = None
-        self._weight = 1
-
-    def __call__(self):
-        "Return the 'obj' that self currently references."
-        return self._findrep()._obj
-
-    def _findrep(self):
-        p = self._parent
-        if p:
-            if p._parent:
-                # this linked list is unnecessarily long, shorten it
-                path = [self]
-                while p._parent:
-                    path.append(p)
-                    p = p._parent
-                for q in path:
-                    q._parent = p
-            return p
-        return self
-
-    def merge(self, other, union=None):
-        "Merge two references.  After a.merge(b), a() and b() are identical."
-        self  = self ._findrep()
-        other = other._findrep()
-        if self is not other:
-            w1 = self ._weight
-            w2 = other._weight
-            if w1 < w2:
-                self, other = other, self
-            self._weight = w1 + w2
-            other._parent = self
-            o = other._obj
-            del other._obj
-            if union is not None:
-                self._obj = union(self._obj, o)
-            else:
-                self.update(o)
-        return self
-
-    def update(self, obj):
-        "Merge 'obj' in self.  Default implementation, can be overridden."
-        self._obj.update(obj)
-
-    def __hash__(self):
-        raise TypeError("UnionRef objects are unhashable")
-
-    def __eq__(self, other):
-        return (isinstance(other, UnionRef) and
-                self._findrep() is other._findrep())
-
-    def __ne__(self, other):
-        return not (self == other)
-
-
-class UnionDict(object, UserDict.DictMixin):
-    """Mapping class whose items can be unified.  Conceptually, instead of
-    a set of (key, value) pairs, this is a set of ({keys}, value) pairs.
-    The method merge(key1, key2) merges the two pairs containing, respectively,
-    key1 and key2.
-    """
-    _slots = ('_data',)
-
-    def __init__(self, dict=None, **kwargs):
-        self._data = {}
-        if dict is not None:
-            self.update(dict)
-        if len(kwargs):
-            self.update(kwargs)
-
-    def merge(self, key1, key2, union=None):
-        self._data[key1] = self._data[key1].merge(self._data[key2], union)
-
-    def copy(self):
-        result = UnionDict()
-        newrefs = {}
-        for key, valueref in self._data.iteritems():
-            valueref = valueref._findrep()
-            try:
-                newref = newrefs[valueref]
-            except KeyError:
-                newref = newrefs[valueref] = UnionRef(valueref())
-            result._data[key] = newref
-        return result
-
-    def __repr__(self):
-        return "<UnionDict at 0x%x>" % uid(self)
-
-    def __getitem__(self, key):
-        return self._data[key]()
-
-    def __setitem__(self, key, value):
-        self._data[key] = UnionRef(value)
-
-    def __delitem__(self, key):
-        del self._data[key]
-
-    def keys(self):
-        return self._data.keys()
-
-    def has_key(self, key):
-        return key in self._data
-
-    def __contains__(self, key):
-        return key in self._data
-
-    def __iter__(self):
-        return iter(self._data)
-
-    def iteritems(self):
-        for key, valueref in self._data.iteritems():
-            yield (key, valueref())
-
-    def clear(self):
-        self._data.clear()
-
-    def popitem(self):
-        key, valueref = self._data.popitem()
-        return key, valueref()
-
-    def __len__(self):
-        return len(self._data)


More information about the pypy-commit mailing list