[pypy-svn] r65577 - in pypy/branch/pyjitpl5-experiments/pypy: jit/backend/x86 jit/backend/x86/test rpython/lltypesystem rpython/memory/gctransform

arigo at codespeak.net arigo at codespeak.net
Thu Jun 4 15:51:20 CEST 2009


Author: arigo
Date: Thu Jun  4 15:51:20 2009
New Revision: 65577

Modified:
   pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/assembler.py
   pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/gc.py
   pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/regalloc.py
   pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/runner.py
   pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/test/test_zrpy_gc.py
   pypy/branch/pyjitpl5-experiments/pypy/rpython/lltypesystem/lloperation.py
   pypy/branch/pyjitpl5-experiments/pypy/rpython/memory/gctransform/framework.py
Log:
Allow allocation of strings and unicodes with the framework GC in the JIT.


Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/assembler.py
==============================================================================
--- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/assembler.py	(original)
+++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/assembler.py	Thu Jun  4 15:51:20 2009
@@ -92,6 +92,8 @@
         self.verbose = False
         self.rtyper = cpu.rtyper
         self.malloc_func_addr = 0
+        self.malloc_str_func_addr = 0
+        self.malloc_unicode_func_addr = 0
         self._exception_data = lltype.nullptr(rffi.CArray(lltype.Signed))
         self._exception_addr = 0
         self.mcstack = MachineCodeStack()
@@ -125,16 +127,25 @@
             self.mc = self.mcstack.next_mc()
             self.mc2 = self.mcstack.next_mc()
             # the address of the function called by 'new'
-            ll_new = self.cpu.gc_ll_descr.get_funcptr_for_new()
+            gc_ll_descr = self.cpu.gc_ll_descr
+            ll_new = gc_ll_descr.get_funcptr_for_new()
             self.malloc_func_addr = rffi.cast(lltype.Signed, ll_new)
+            if gc_ll_descr.get_funcptr_for_newstr is not None:
+                ll_new_str = gc_ll_descr.get_funcptr_for_newstr()
+                self.malloc_str_func_addr = rffi.cast(lltype.Signed,
+                                                      ll_new_str)
+            if gc_ll_descr.get_funcptr_for_newunicode is not None:
+                ll_new_unicode = gc_ll_descr.get_funcptr_for_newunicode()
+                self.malloc_unicode_func_addr = rffi.cast(lltype.Signed,
+                                                          ll_new_unicode)
             # for moving GCs, the array used to hold the address of GC objects
             # that appear as ConstPtr.
-            if self.cpu.gc_ll_descr.moving_gc:
-                self.gcrefs = self.cpu.gc_ll_descr.GcRefList()
+            if gc_ll_descr.moving_gc:
+                self.gcrefs = gc_ll_descr.GcRefList()
                 self.single_gcref_descr = ConstDescr3(0, WORD, True)
             else:
                 self.gcrefs = None
-            self.gcrootmap = self.cpu.gc_ll_descr.gcrootmap
+            self.gcrootmap = gc_ll_descr.gcrootmap
             if self.gcrootmap:
                 self.gcrootmap.initialize()
 
@@ -316,7 +327,7 @@
             assert not isinstance(arg, MODRM)
             self.mc.PUSH(arg)
         self.mc.CALL(rel32(addr))
-        self.mark_gc_roots(len(args))
+        self.mark_gc_roots()
         self.mc.ADD(esp, imm(len(args) * WORD))
         assert res is eax
 
@@ -466,6 +477,14 @@
         assert result_loc is eax
         self.call(self.malloc_func_addr, arglocs, eax)
 
+    def genop_newstr(self, op, arglocs, result_loc):
+        assert result_loc is eax
+        self.call(self.malloc_str_func_addr, arglocs, eax)
+
+    def genop_newunicode(self, op, arglocs, result_loc):
+        assert result_loc is eax
+        self.call(self.malloc_unicode_func_addr, arglocs, eax)
+
     def genop_getfield_gc(self, op, arglocs, resloc):
         base_loc, ofs_loc, size_loc = arglocs
         assert isinstance(size_loc, IMM32)
@@ -758,7 +777,7 @@
             if isinstance(x, MODRM):
                 x = stack_pos(x.position)
         self.mc.CALL(x)
-        self.mark_gc_roots(extra_on_stack)
+        self.mark_gc_roots()
         self.mc.ADD(esp, imm(WORD * extra_on_stack))
         if size == 1:
             self.mc.AND(eax, imm(0xff))
@@ -788,7 +807,7 @@
     #    self.gen_call(op, arglocs, resloc)
     #    self.mc.MOVZX(eax, eax)
 
-    def mark_gc_roots(self, extra_on_stack):
+    def mark_gc_roots(self):
         if self.gcrootmap:
             gclocs = []
             regalloc = self._regalloc

Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/gc.py
==============================================================================
--- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/gc.py	(original)
+++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/gc.py	Thu Jun  4 15:51:20 2009
@@ -1,5 +1,5 @@
 from pypy.rlib import rgc
-from pypy.rpython.lltypesystem import lltype, llmemory, rffi, rclass
+from pypy.rpython.lltypesystem import lltype, llmemory, rffi, rclass, rstr
 from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.rpython.annlowlevel import llhelper
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
@@ -7,6 +7,7 @@
 from pypy.jit.backend.x86.runner import ConstDescr3
 from pypy.jit.backend.x86.ri386 import MODRM, IMM32, mem, imm32, rel32, heap
 from pypy.jit.backend.x86.ri386 import REG, eax, ecx, edx
+from pypy.jit.backend.x86.assembler import WORD
 
 # ____________________________________________________________
 
@@ -51,7 +52,26 @@
         basesize = arraydescr.v0
         itemsize = arraydescr.v1
         size = basesize + itemsize * num_elem
-        return self.funcptr_for_new(size)
+        res = self.funcptr_for_new(size)
+        rffi.cast(rffi.CArrayPtr(lltype.Signed), res)[0] = num_elem
+        return res
+
+    def gc_malloc_str(self, num_elem, translate_support_code):
+        basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR,
+                                                      translate_support_code)
+        assert itemsize == 1
+        size = basesize + num_elem
+        res = self.funcptr_for_new(size)
+        rffi.cast(rffi.CArrayPtr(lltype.Signed), res)[ofs_length/WORD] = num_elem
+        return res
+
+    def gc_malloc_unicode(self, num_elem, translate_support_code):
+        basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.UNICODE,
+                                                      translate_support_code)
+        size = basesize + num_elem * itemsize
+        res = self.funcptr_for_new(size)
+        rffi.cast(rffi.CArrayPtr(lltype.Signed), res)[ofs_length/WORD] = num_elem
+        return res
 
     def args_for_new(self, descrsize):
         assert isinstance(descrsize, ConstDescr3)
@@ -61,6 +81,9 @@
     def get_funcptr_for_new(self):
         return self.funcptr_for_new
 
+    get_funcptr_for_newstr = None
+    get_funcptr_for_newunicode = None
+
 # ____________________________________________________________
 
 class GcRefList:
@@ -271,6 +294,28 @@
             [lltype.Signed, lltype.Signed, lltype.Bool], llmemory.GCREF))
         self.WB_FUNCPTR = lltype.Ptr(lltype.FuncType(
             [llmemory.Address, llmemory.Address], lltype.Void))
+        #
+        (str_basesize, str_itemsize, str_ofs_length
+         ) = symbolic.get_array_token(rstr.STR, True)
+        (unicode_basesize, unicode_itemsize, unicode_ofs_length
+         ) = symbolic.get_array_token(rstr.UNICODE, True)
+        str_type_id = self.layoutbuilder.get_type_id(rstr.STR)
+        unicode_type_id = self.layoutbuilder.get_type_id(rstr.UNICODE)
+        #
+        def malloc_str(length):
+            return llop.do_malloc_varsize_clear(
+                llmemory.GCREF,
+                str_type_id, length, str_basesize, str_itemsize,
+                str_ofs_length, True, False)
+        def malloc_unicode(length):
+            return llop.do_malloc_varsize_clear(
+                llmemory.GCREF,
+                unicode_type_id, length, unicode_basesize, unicode_itemsize,
+                unicode_ofs_length, True, False)
+        self.malloc_str = malloc_str
+        self.malloc_unicode = malloc_unicode
+        self.GC_MALLOC_STR_UNICODE = lltype.Ptr(lltype.FuncType(
+            [lltype.Signed], llmemory.GCREF))
 
     def sizeof(self, S, translate_support_code):
         from pypy.rpython.memory.gctypelayout import weakpointer_offset
@@ -292,6 +337,14 @@
     def gc_malloc_array(self, arraydescr, num_elem):
         raise NotImplementedError
 
+    def gc_malloc_str(self, num_elem, translate_support_code):
+        assert translate_support_code, "required with the framework GC"
+        return self.malloc_str(num_elem)
+
+    def gc_malloc_unicode(self, num_elem, translate_support_code):
+        assert translate_support_code, "required with the framework GC"
+        return self.malloc_unicode(num_elem)
+
     def args_for_new(self, descrsize):
         assert isinstance(descrsize, ConstDescr3)
         size = descrsize.v0
@@ -302,6 +355,12 @@
     def get_funcptr_for_new(self):
         return llhelper(self.GC_MALLOC_BASIC, self.malloc_basic)
 
+    def get_funcptr_for_newstr(self):
+        return llhelper(self.GC_MALLOC_STR_UNICODE, self.malloc_str)
+
+    def get_funcptr_for_newunicode(self):
+        return llhelper(self.GC_MALLOC_STR_UNICODE, self.malloc_unicode)
+
     def do_write_barrier(self, gcref_struct, gcref_newptr):
         hdr_addr = llmemory.cast_ptr_to_adr(gcref_struct)
         hdr = llmemory.cast_adr_to_ptr(hdr_addr, self.HDRPTR)

Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/regalloc.py
==============================================================================
--- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/regalloc.py	(original)
+++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/regalloc.py	Thu Jun  4 15:51:20 2009
@@ -952,23 +952,35 @@
         return self._call(op, arglocs)
 
     def consider_newstr(self, op, ignored):
+        gc_ll_descr = self.assembler.cpu.gc_ll_descr
+        if gc_ll_descr.get_funcptr_for_newstr is not None:
+            # framework GC
+            loc = self.loc(op.args[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.STR, self.translate_support_code)
         assert itemsize == 1
-        return self._malloc_varsize(0, ofs_items, ofs, 0, op.args[0],
+        return self._malloc_varsize(ofs_items, ofs, 0, op.args[0],
                                     op.result)
 
     def consider_newunicode(self, op, ignored):
+        gc_ll_descr = self.assembler.cpu.gc_ll_descr
+        if gc_ll_descr.get_funcptr_for_newunicode is not None:
+            # framework GC
+            loc = self.loc(op.args[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(0, ofs_items, ofs, 2, op.args[0],
+            return self._malloc_varsize(ofs_items, ofs, 2, op.args[0],
                                         op.result)
         elif itemsize == 2:
-            return self._malloc_varsize(0, ofs_items, ofs, 1, op.args[0],
+            return self._malloc_varsize(ofs_items, ofs, 1, op.args[0],
                                         op.result)
         else:
             assert False, itemsize
 
-    def _malloc_varsize(self, ofs, ofs_items, ofs_length, size, v, res_v):
+    def _malloc_varsize(self, ofs_items, ofs_length, size, v, res_v):
         if isinstance(v, Box):
             loc = self.make_sure_var_in_reg(v, [v])
             self.sync_var(v)
@@ -978,9 +990,9 @@
                 self.Perform(ResOperation(rop.INT_MUL, [], None),
                              [loc, imm(1 << size)], loc)
             self.Perform(ResOperation(rop.INT_ADD, [], None),
-                         [loc, imm(ofs + ofs_items)], loc)
+                         [loc, imm(ofs_items)], loc)
         else:
-            loc = imm(ofs + ofs_items + (v.getint() << size))
+            loc = imm(ofs_items + (v.getint() << size))
         self._call(ResOperation(rop.NEW, [v], res_v),
                    [loc], [v])
         loc = self.make_sure_var_in_reg(v, [res_v])
@@ -988,11 +1000,11 @@
         # now we have to reload length to some reasonable place
         self.eventually_free_var(v)
         self.PerformDiscard(ResOperation(rop.SETFIELD_GC, [], None),
-                            [eax, imm(ofs + ofs_length), imm(WORD), loc])
+                            [eax, imm(ofs_length), imm(WORD), loc])
 
     def consider_new_array(self, op, ignored):
         size_of_field, basesize, _ = self._unpack_arraydescr(op.descr)
-        return self._malloc_varsize(0, basesize, 0, size_of_field, op.args[0],
+        return self._malloc_varsize(basesize, 0, size_of_field, op.args[0],
                                     op.result)
 
     def _unpack_arraydescr(self, arraydescr):

Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/runner.py
==============================================================================
--- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/runner.py	(original)
+++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/runner.py	Thu Jun  4 15:51:20 2009
@@ -538,22 +538,19 @@
     def do_new_array(self, args, arraydescr):
         num_elem = args[0].getint()
         res = self.gc_ll_descr.gc_malloc_array(arraydescr, num_elem)
-        rffi.cast(rffi.CArrayPtr(lltype.Signed), res)[0] = num_elem
-        # XXX don't use 0 above!
         return BoxPtr(self.cast_adr_to_gcref(res))
 
-    def _new_do_newstr(TP):
-        def do_newstr(self, args, descr=0):
-            basesize, itemsize, ofs_length = symbolic.get_array_token(TP,
-                                             self.translate_support_code)
-            num_elem = args[0].getint()
-            size = basesize + num_elem * itemsize
-            res = self.gc_ll_descr.funcptr_for_new(size)    # XXX don't use
-            rffi.cast(rffi.CArrayPtr(lltype.Signed), res)[ofs_length/WORD] = num_elem
-            return BoxPtr(self.cast_adr_to_gcref(res))
-        return do_newstr
-    do_newstr = _new_do_newstr(rstr.STR)
-    do_newunicode = _new_do_newstr(rstr.UNICODE)
+    def do_newstr(self, args, descr=0):
+        num_elem = args[0].getint()
+        tsc = self.translate_support_code
+        res = self.gc_ll_descr.gc_malloc_str(num_elem, tsc)
+        return BoxPtr(self.cast_adr_to_gcref(res))
+
+    def do_newunicode(self, args, descr=0):
+        num_elem = args[0].getint()
+        tsc = self.translate_support_code
+        res = self.gc_ll_descr.gc_malloc_unicode(num_elem, tsc)
+        return BoxPtr(self.cast_adr_to_gcref(res))
 
     def do_strsetitem(self, args, descr=0):
         basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR,

Modified: pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/test/test_zrpy_gc.py
==============================================================================
--- pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/test/test_zrpy_gc.py	(original)
+++ pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/test/test_zrpy_gc.py	Thu Jun  4 15:51:20 2009
@@ -207,3 +207,18 @@
     res = compile_and_run(get_test(main), "hybrid", gcrootfinder="asmgcc",
                           jit=True)
     assert int(res) == 20
+
+def test_compile_hybrid_5():
+    # Test string manipulation.
+    myjitdriver = JitDriver(greens = [], reds = ['n', 'x', 's'])
+    def main(n, x):
+        s = ''
+        while n > 0:
+            myjitdriver.can_enter_jit(n=n, x=x, s=s)
+            myjitdriver.jit_merge_point(n=n, x=x, s=s)
+            n -= x.foo
+            s += str(n)
+        assert len(s) == 1*5 + 2*45 + 3*450 + 4*500
+    res = compile_and_run(get_test(main), "hybrid", gcrootfinder="asmgcc",
+                          jit=True)
+    assert int(res) == 20

Modified: pypy/branch/pyjitpl5-experiments/pypy/rpython/lltypesystem/lloperation.py
==============================================================================
--- pypy/branch/pyjitpl5-experiments/pypy/rpython/lltypesystem/lloperation.py	(original)
+++ pypy/branch/pyjitpl5-experiments/pypy/rpython/lltypesystem/lloperation.py	Thu Jun  4 15:51:20 2009
@@ -388,6 +388,7 @@
     'get_exception_addr':   LLOp(),
     'get_exc_value_addr':   LLOp(),
     'do_malloc_fixedsize_clear': LLOp(),
+    'do_malloc_varsize_clear': LLOp(),
     'get_write_barrier_failing_case': LLOp(sideeffects=False),
 
     # __________ GC operations __________

Modified: pypy/branch/pyjitpl5-experiments/pypy/rpython/memory/gctransform/framework.py
==============================================================================
--- pypy/branch/pyjitpl5-experiments/pypy/rpython/memory/gctransform/framework.py	(original)
+++ pypy/branch/pyjitpl5-experiments/pypy/rpython/memory/gctransform/framework.py	Thu Jun  4 15:51:20 2009
@@ -617,6 +617,17 @@
                    v_has_finalizer, v_contains_weakptr],
                   resultvar=op.result)
 
+    def gct_do_malloc_varsize_clear(self, hop):
+        # used by the JIT (see the x86 backend)
+        op = hop.spaceop
+        [v_typeid, v_length, v_size, v_itemsize,
+         v_offset_to_length, v_can_collect, v_has_finalizer] = op.args
+        hop.genop("direct_call",
+                  [self.malloc_varsize_clear_ptr, self.c_const_gc,
+                   v_typeid, v_length, v_size, v_itemsize,
+                   v_offset_to_length, v_can_collect, v_has_finalizer],
+                  resultvar=op.result)
+
     def gct_get_write_barrier_failing_case(self, hop):
         op = hop.spaceop
         hop.genop("same_as",



More information about the Pypy-commit mailing list