Commits

Armin Rigo  committed 95bf5e4

some translation fixes

  • Participants
  • Parent commits 3b9e329
  • Branches stringbuilder-perf

Comments (0)

Files changed (5)

File rpython/rtyper/annlowlevel.py

         return LowLevelAnnotatorPolicy.lowlevelspecialize(funcdesc, args_s, {})
     default_specialize = staticmethod(default_specialize)
 
-    def specialize__semierased(funcdesc, args_s):
-        a2l = annotation_to_lltype
-        l2a = lltype_to_annotation
-        args_s[:] = [l2a(a2l(s)) for s in args_s]
-        return LowLevelAnnotatorPolicy.default_specialize(funcdesc, args_s)
-    specialize__semierased = staticmethod(specialize__semierased)
-
     specialize__ll = default_specialize
 
     def specialize__ll_and_arg(funcdesc, args_s, *argindices):

File rpython/rtyper/lltypesystem/rbuilder.py

 from rpython.rtyper.rbuilder import AbstractStringBuilderRepr
 from rpython.tool.sourcetools import func_with_new_name
 from rpython.rtyper.llannotation import SomePtr
+from rpython.rtyper.annlowlevel import llstr
 from rpython.rlib.objectmodel import we_are_translated
 from rpython.rlib.rgc import must_be_light_finalizer
 
 
     @staticmethod
     def ll_append_charpsize(ll_builder, charp, size):
-        XXX
-        used = ll_builder.used
-        if used + size > ll_builder.allocated:
-            ll_builder.grow(ll_builder, size)
-        ll_builder.copy_raw_to_string(charp, ll_builder.buf, used, size)
-        ll_builder.used += size
+        lgt = size
+        ofs = ll_builder.current_ofs
+        newofs = ofs + lgt
+        if newofs > ll_builder.current_end:
+            ll_str = llstr(rffi.charpsize2str(charp, size))
+            ll_builder.append_overflow(ll_builder, ll_str)
+        else:
+            ll_builder.current_ofs = newofs
+            # --- no GC! ---
+            raw = rffi.cast(rffi.CCHARP, ll_builder.current_buf)
+            rffi.c_memcpy(rffi.ptradd(raw, ofs),
+                          charp,
+                          lgt)
+            # --- end ---
 
     @staticmethod
     def ll_getlength(ll_builder):

File rpython/rtyper/lltypesystem/rffi.py

         from rpython.rtyper.lltypesystem.rstr import (STR as STRTYPE,
                                                       copy_string_to_raw,
                                                       copy_raw_to_string,
-                                                      copy_string_contents)
+                                                      copy_string_contents,
+                                                      mallocstr as mallocfn)
         from rpython.rtyper.annlowlevel import llstr as llstrtype
         from rpython.rtyper.annlowlevel import hlstr as hlstrtype
         TYPEP = CCHARP
         ll_char_type = lltype.Char
         lastchar = '\x00'
-        builder_class = StringBuilder
     else:
         from rpython.rtyper.lltypesystem.rstr import (
             UNICODE as STRTYPE,
             copy_unicode_to_raw as copy_string_to_raw,
             copy_raw_to_unicode as copy_raw_to_string,
-            copy_unicode_contents as copy_string_contents)
+            copy_unicode_contents as copy_string_contents,
+            mallocunicode as mallocfn)
         from rpython.rtyper.annlowlevel import llunicode as llstrtype
         from rpython.rtyper.annlowlevel import hlunicode as hlstrtype
         TYPEP = CWCHARP
         ll_char_type = lltype.UniChar
         lastchar = u'\x00'
-        builder_class = UnicodeBuilder
 
     # str -> char*
     def str2charp(s, track_allocation=True):
         size = 0
         while cp[size] != lastchar:
             size += 1
-        b = builder_class(size)
-        i = 0
-        while cp[i] != lastchar:
-            b.append(cp[i])
-            i += 1
-        return assert_str0(b.build())
+        return assert_str0(charpsize2str(cp, size))
 
     # str -> char*
     # Can't inline this because of the raw address manipulation.
     # char* -> str, with an upper bound on the length in case there is no \x00
     @enforceargs(None, int)
     def charp2strn(cp, maxlen):
-        b = builder_class(maxlen)
-        i = 0
-        while i < maxlen and cp[i] != lastchar:
-            b.append(cp[i])
-            i += 1
-        return assert_str0(b.build())
+        size = 0
+        while size < maxlen and cp[size] != lastchar:
+            size += 1
+        return assert_str0(charpsize2str(cp, size))
 
     # char* and size -> str (which can contain null bytes)
     def charpsize2str(cp, size):
-        b = builder_class(size)
-        b.append_charpsize(cp, size)
-        return b.build()
+        ll_str = mallocfn(size)
+        copy_raw_to_string(cp, ll_str, 0, size)
+        return hlstrtype(ll_str)
     charpsize2str._annenforceargs_ = [None, int]
 
     return (str2charp, free_charp, charp2str,

File rpython/rtyper/lltypesystem/rstr.py

 from rpython.rlib import jit, types
 from rpython.rlib.debug import ll_assert
 from rpython.rlib.objectmodel import (malloc_zero_filled, we_are_translated,
-    _hash_string, keepalive_until_here, specialize)
+    _hash_string, keepalive_until_here, specialize, enforceargs)
 from rpython.rlib.signature import signature
 from rpython.rlib.rarithmetic import ovfcheck
 from rpython.rtyper.error import TyperError
 UNICODE = GcForwardReference()
 
 def new_malloc(TP, name):
+    @enforceargs(int)
     def mallocstr(length):
         ll_assert(length >= 0, "negative string length")
         r = malloc(TP, length)
         if not we_are_translated() or not malloc_zero_filled:
             r.hash = 0
         return r
-    mallocstr._annspecialcase_ = 'specialize:semierased'
     return func_with_new_name(mallocstr, name)
 
 mallocstr = new_malloc(STR, 'mallocstr')

File rpython/rtyper/test/test_rbuilder.py

 from rpython.rlib.rstring import StringBuilder, UnicodeBuilder
 from rpython.rtyper.annlowlevel import llstr, hlstr
 from rpython.rtyper.lltypesystem import rffi
-from rpython.rtyper.lltypesystem.rbuilder import StringBuilderRepr
+from rpython.rtyper.lltypesystem.rbuilder import StringBuilderRepr, UnicodeBuilderRepr
 from rpython.rtyper.test.tool import BaseRtypingTest
 
 
         s = StringBuilderRepr.ll_build(sb)
         assert hlstr(s) == "abc" * 11 + "def"
 
+    def test_charp(self):
+        sb = StringBuilderRepr.ll_new(32)
+        with rffi.scoped_str2charp("hello world") as p:
+            StringBuilderRepr.ll_append_charpsize(sb, p, 12)
+        with rffi.scoped_str2charp("0123456789abcdefghijklmn") as p:
+            StringBuilderRepr.ll_append_charpsize(sb, p, 24)
+        s = StringBuilderRepr.ll_build(sb)
+        assert hlstr(s) == "hello world\x000123456789abcdefghijklmn"
+
+    def test_unicode(self):
+        sb = UnicodeBuilderRepr.ll_new(3)
+        UnicodeBuilderRepr.ll_append_char(sb, u'x')
+        UnicodeBuilderRepr.ll_append(sb, llstr(u"abc"))
+        UnicodeBuilderRepr.ll_append_slice(sb, llstr(u"foobar"), 2, 5)
+        UnicodeBuilderRepr.ll_append_multiple_char(sb, u'y', 3)
+        u = UnicodeBuilderRepr.ll_build(sb)
+        assert u''.join(u.chars) == u"xabcobayyy"
+
 
 class TestStringBuilder(BaseRtypingTest):
     def test_simple(self):