[pypy-commit] pypy fast-newarray: implement the case for string and unicode too

fijal noreply at buildbot.pypy.org
Mon Apr 15 23:04:20 CEST 2013


Author: Maciej Fijalkowski <fijall at gmail.com>
Branch: fast-newarray
Changeset: r63392:fed361ad6aaa
Date: 2013-04-15 23:03 +0200
http://bitbucket.org/pypy/pypy/changeset/fed361ad6aaa/

Log:	implement the case for string and unicode too

diff --git a/rpython/jit/backend/llsupport/assembler.py b/rpython/jit/backend/llsupport/assembler.py
--- a/rpython/jit/backend/llsupport/assembler.py
+++ b/rpython/jit/backend/llsupport/assembler.py
@@ -85,8 +85,20 @@
             self._build_wb_slowpath(True, withfloats=True)
         self._build_propagate_exception_path()
         if gc_ll_descr.get_malloc_slowpath_addr is not None:
-            self.malloc_slowpath = self._build_malloc_slowpath(varsize=False)
-            self.malloc_slowpath_varsize = self._build_malloc_slowpath(varsize=True)
+            # generate few slowpaths for various cases
+            self.malloc_slowpath = self._build_malloc_slowpath(kind='fixed')
+            self.malloc_slowpath_varsize = self._build_malloc_slowpath(
+                kind='var')
+        if hasattr(gc_ll_descr, 'malloc_str'):
+            self.malloc_slowpath_str = self._build_malloc_slowpath(kind='str')
+        else:
+            self.malloc_slowpath_str = None
+        if hasattr(gc_ll_descr, 'malloc_unicode'):
+            self.malloc_slowpath_unicode = self._build_malloc_slowpath(
+                kind='unicode')
+        else:
+            self.malloc_slowpath_unicode = None
+
         self._build_stack_check_slowpath()
         if gc_ll_descr.gcrootmap:
             self._build_release_gil(gc_ll_descr.gcrootmap)
diff --git a/rpython/jit/backend/llsupport/rewrite.py b/rpython/jit/backend/llsupport/rewrite.py
--- a/rpython/jit/backend/llsupport/rewrite.py
+++ b/rpython/jit/backend/llsupport/rewrite.py
@@ -102,9 +102,11 @@
             assert isinstance(descr, ArrayDescr)
             self.handle_new_array(descr, op)
         elif opnum == rop.NEWSTR:
-            self.handle_new_array(self.gc_ll_descr.str_descr, op)
+            self.handle_new_array(self.gc_ll_descr.str_descr, op,
+                                  kind=FLAG_STR)
         elif opnum == rop.NEWUNICODE:
-            self.handle_new_array(self.gc_ll_descr.unicode_descr, op)
+            self.handle_new_array(self.gc_ll_descr.unicode_descr, op,
+                                  kind=FLAG_UNICODE)
         else:
             raise NotImplementedError(op.getopname())
 
@@ -116,7 +118,7 @@
         else:
             self.gen_malloc_fixedsize(size, descr.tid, op.result)
 
-    def handle_new_array(self, arraydescr, op):
+    def handle_new_array(self, arraydescr, op, kind=FLAG_ARRAY):
         v_length = op.getarg(0)
         total_size = -1
         if isinstance(v_length, ConstInt):
@@ -131,7 +133,7 @@
             total_size = arraydescr.basesize
         elif (self.gc_ll_descr.can_use_nursery_malloc(1) and
               self.gen_malloc_nursery_varsize(arraydescr.itemsize,
-              v_length, op.result, arraydescr)):
+              v_length, op.result, arraydescr, kind=kind)):
             # note that we cannot initialize tid here, because the array
             # might end up being allocated by malloc_external or some
             # stuff that initializes GC header fields differently
@@ -300,28 +302,17 @@
                                  self.gc_ll_descr.malloc_unicode_descr)
 
     def gen_malloc_nursery_varsize(self, itemsize, v_length, v_result,
-                                   arraydescr):
+                                   arraydescr, kind=FLAG_ARRAY):
         """ itemsize is an int, v_length and v_result are boxes
         """
         gc_descr = self.gc_ll_descr
-        str_descr = gc_descr.str_descr
-        unicode_descr = gc_descr.unicode_descr
-        if (arraydescr.basesize == gc_descr.standard_array_basesize and
-            arraydescr.lendescr.offset == gc_descr.standard_array_length_ofs):
-            flag = FLAG_ARRAY # standard array
-        elif (arraydescr.basesize == str_descr.basesize and
-              arraydescr.lendescr.offset == str_descr.lendescr.offset):
-            flag = FLAG_STR
-        elif (arraydescr.basesize == unicode_descr.basesize and
-              arraydescr.lendescr.offset == unicode_descr.lendescr.offset):
-            # note that this might never be reached if we have the same
-            # offsets, that does not quite matter though
-            flag = FLAG_UNICODE
-        else:
+        if (kind == FLAG_ARRAY and
+            (arraydescr.basesize != gc_descr.standard_array_basesize or
+             arraydescr.lendescr.offset != gc_descr.standard_array_length_ofs)):
             return False
         self.emitting_an_operation_that_can_collect()
         op = ResOperation(rop.CALL_MALLOC_NURSERY_VARSIZE,
-                          [ConstInt(flag), ConstInt(itemsize), v_length],
+                          [ConstInt(kind), ConstInt(itemsize), v_length],
                           v_result, descr=arraydescr)
         self.newops.append(op)
         self.recent_mallocs[v_result] = None
diff --git a/rpython/jit/backend/llsupport/test/test_gc_integration.py b/rpython/jit/backend/llsupport/test/test_gc_integration.py
--- a/rpython/jit/backend/llsupport/test/test_gc_integration.py
+++ b/rpython/jit/backend/llsupport/test/test_gc_integration.py
@@ -263,8 +263,8 @@
         arraydescr.tid = 15
         ops = '''
         [i0, i1, i2]
-        p0 = call_malloc_nursery_varsize(8, i0, descr=arraydescr)
-        p1 = call_malloc_nursery_varsize(5, i1, descr=arraydescr)
+        p0 = call_malloc_nursery_varsize(0, 8, i0, descr=arraydescr)
+        p1 = call_malloc_nursery_varsize(0, 5, i1, descr=arraydescr)
         guard_false(i0) [p0, p1]
         '''
         self.interpret(ops, [1, 2, 3],
@@ -286,10 +286,10 @@
         self.cpu = self.getcpu(None)
         ops = '''
         [i0, i1, i2]
-        p0 = call_malloc_nursery_varsize(8, i0, descr=arraydescr)
-        p1 = call_malloc_nursery_varsize(5, i1, descr=arraydescr)
-        p3 = call_malloc_nursery_varsize(5, i2, descr=arraydescr)
-        p4 = call_malloc_nursery_varsize(5, i2, descr=arraydescr)
+        p0 = call_malloc_nursery_varsize(0, 8, i0, descr=arraydescr)
+        p1 = call_malloc_nursery_varsize(0, 5, i1, descr=arraydescr)
+        p3 = call_malloc_nursery_varsize(0, 5, i2, descr=arraydescr)
+        p4 = call_malloc_nursery_varsize(0, 5, i2, descr=arraydescr)
         # overflow
         guard_false(i0) [p0, p1, p3, p4]
         '''
@@ -816,7 +816,7 @@
         pdying = getarrayitem_gc(p0, 0, descr=arraydescr)
         px = call_may_force(ConstClass(fptr), pf, pdying, i0, descr=calldescr)
         guard_not_forced(descr=faildescr) [p1, p2, p3, px]
-        finish(px, descr=finishdescr)
+        finish(px, descr=finaldescr)
         """, namespace={'fptr': fptr, 'calldescr': calldescr,
                         'arraydescr': cpu.arraydescrof(A),
                         'faildescr': BasicFailDescr(1),
@@ -860,7 +860,7 @@
         pdying = getarrayitem_gc(p0, 0, descr=arraydescr)
         px = call(ConstClass(fptr), pf, pdying, i0, descr=calldescr)
         guard_false(i0, descr=faildescr) [p1, p2, p3, px]
-        finish(px, descr=finishdescr)
+        finish(px, descr=finaldescr)
         """, namespace={'fptr': fptr, 'calldescr': calldescr,
                         'arraydescr': cpu.arraydescrof(A),
                         'faildescr': BasicFailDescr(1),
diff --git a/rpython/jit/backend/llsupport/test/test_rewrite.py b/rpython/jit/backend/llsupport/test/test_rewrite.py
--- a/rpython/jit/backend/llsupport/test/test_rewrite.py
+++ b/rpython/jit/backend/llsupport/test/test_rewrite.py
@@ -545,7 +545,7 @@
             p1 = int_add(p0, %(strdescr.basesize + 16 * strdescr.itemsize)d)
             setfield_gc(p1, %(unicodedescr.tid)d, descr=tiddescr)
             setfield_gc(p1, 10, descr=unicodelendescr)
-            p2 = call_malloc_nursery_varsize(1, 4, i2, \
+            p2 = call_malloc_nursery_varsize(2, 4, i2, \
                                 descr=unicodedescr)
             setfield_gc(p2, i2, descr=unicodelendescr)
             p3 = call_malloc_nursery_varsize(1, 1, i2, \
diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py
--- a/rpython/jit/backend/x86/assembler.py
+++ b/rpython/jit/backend/x86/assembler.py
@@ -1,7 +1,7 @@
 import sys
 import os
 
-from rpython.jit.backend.llsupport import symbolic, jitframe
+from rpython.jit.backend.llsupport import symbolic, jitframe, gc
 from rpython.jit.backend.llsupport.assembler import (GuardToken, BaseAssembler,
                                                 DEBUG_COUNTER, debug_bridge)
 from rpython.jit.backend.llsupport.asmmemmgr import MachineDataBlockWrapper
@@ -156,22 +156,27 @@
         mc.RET()
         self._frame_realloc_slowpath = mc.materialize(self.cpu.asmmemmgr, [])
 
-    def _build_malloc_slowpath(self, varsize):
+    def _build_malloc_slowpath(self, kind):
         """ While arriving on slowpath, we have a gcpattern on stack,
         nursery_head in eax and the size in edi - eax
         """
+        assert kind in ['fixed', 'str', 'unicode', 'var']
         mc = codebuf.MachineCodeBlockWrapper()
         self._push_all_regs_to_frame(mc, [eax, edi], self.cpu.supports_floats)
         ofs = self.cpu.get_ofs_of_frame_field('jf_gcmap')
         # store the gc pattern
         mc.MOV_rs(ecx.value, WORD)
         mc.MOV_br(ofs, ecx.value)
-        if varsize:
+        if kind == 'fixed':
+            addr = self.cpu.gc_ll_descr.get_malloc_slowpath_addr()
+        elif kind == 'str':
+            addr = self.cpu.gc_ll_descr.get_malloc_fn_addr('malloc_str')
+        elif kind == 'unicode':
+            addr = self.cpu.gc_ll_descr.get_malloc_fn_addr('malloc_unicode')
+        else:
             addr = self.cpu.gc_ll_descr.get_malloc_slowpath_array_addr()
-        else:
-            addr = self.cpu.gc_ll_descr.get_malloc_slowpath_addr()
         mc.SUB_ri(esp.value, 16 - WORD)
-        if not varsize:
+        if kind == 'fixed':
             mc.SUB_rr(edi.value, eax.value) # compute the size we want
             # the arg is already in edi
             if IS_X86_32:
@@ -181,6 +186,11 @@
             elif hasattr(self.cpu.gc_ll_descr, 'passes_frame'):
                 # for tests only
                 mc.MOV_rr(esi.value, ebp.value)
+        elif kind == 'str' or kind == 'unicode':
+            if IS_X86_32:
+                xxx
+            else:
+                mc.MOV_rs(edi.value, WORD * 3)
         else:
             if IS_X86_32:
                 xxx
@@ -2354,7 +2364,7 @@
         self.mc.overwrite(jmp_adr-1, chr(offset))
         self.mc.MOV(heap(nursery_free_adr), edi)
 
-    def malloc_cond_varsize(self, nursery_free_adr, nursery_top_adr,
+    def malloc_cond_varsize(self, kind, nursery_free_adr, nursery_top_adr,
                             lengthloc, itemsize, maxlength, gcmap,
                             arraydescr):
         from rpython.jit.backend.llsupport.descr import ArrayDescr
@@ -2376,9 +2386,12 @@
         offset = self.mc.get_relative_pos() - jmp_adr0
         assert 0 < offset <= 127
         self.mc.overwrite(jmp_adr0-1, chr(offset))
-        self.mc.MOV_si(WORD, itemsize)
-        self.mc.MOV(RawEspLoc(WORD * 2, INT), lengthloc)
-        self.mc.MOV_si(WORD * 3, arraydescr.tid)
+        if kind == 0:
+            self.mc.MOV_si(WORD, itemsize)
+            self.mc.MOV(RawEspLoc(WORD * 2, INT), lengthloc)
+            self.mc.MOV_si(WORD * 3, arraydescr.tid)
+        else:
+            self.mc.MOV(RawEspLoc(WORD, INT), lengthloc)
         # save the gcmap
         self.push_gcmap(self.mc, gcmap, mov=True)
         self.mc.CALL(imm(self.malloc_slowpath_varsize))
diff --git a/rpython/jit/backend/x86/regalloc.py b/rpython/jit/backend/x86/regalloc.py
--- a/rpython/jit/backend/x86/regalloc.py
+++ b/rpython/jit/backend/x86/regalloc.py
@@ -871,7 +871,7 @@
             sizeloc, gcmap)
 
     def consider_call_malloc_nursery_varsize(self, op):
-        length_box = op.getarg(1)
+        length_box = op.getarg(2)
         arraydescr = op.getdescr()
         assert isinstance(length_box, BoxInt) # we cannot have a const here!
         # looking at the result
@@ -886,9 +886,10 @@
         self.rm.possibly_free_var(tmp_box)
         #
         gc_ll_descr = self.assembler.cpu.gc_ll_descr
-        itemsize = op.getarg(0).getint()
+        itemsize = op.getarg(1).getint()
         maxlength = (gc_ll_descr.max_size_of_young_obj - WORD * 2) / itemsize
         self.assembler.malloc_cond_varsize(
+            op.getarg(0).getint(),
             gc_ll_descr.get_nursery_free_addr(),
             gc_ll_descr.get_nursery_top_addr(),
             lengthloc, itemsize, maxlength, gcmap, arraydescr)


More information about the pypy-commit mailing list