[pypy-svn] r65530 - pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86

arigo at codespeak.net arigo at codespeak.net
Mon Jun 1 18:31:11 CEST 2009


Author: arigo
Date: Mon Jun  1 18:31:10 2009
New Revision: 65530

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
Log:
In-progress: support for write barriers.  "Should work" but
there is a bug somewhere still causing a segfault.


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	Mon Jun  1 18:31:10 2009
@@ -42,6 +42,9 @@
     def tell(self):
         return self._mc.tell()
 
+    def write(self, data):
+        self._mc.write(data)
+
     def done(self):
         self._mc.done()
 

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	Mon Jun  1 18:31:10 2009
@@ -5,15 +5,20 @@
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 from pypy.jit.backend.x86 import symbolic
 from pypy.jit.backend.x86.runner import ConstDescr3
-from pypy.jit.backend.x86.ri386 import MODRM
+from pypy.jit.backend.x86.ri386 import MODRM, mem, imm32, rel32
+from pypy.jit.backend.x86.ri386 import REG, eax, ecx, edx
 
 # ____________________________________________________________
 
 class GcLLDescription:
-    def __init__(self, gcdescr, mixlevelann):
+    def __init__(self, gcdescr, cpu):
         self.gcdescr = gcdescr
     def _freeze_(self):
         return True
+    def do_write_barrier(self, gcref_struct, gcref_newptr):
+        pass
+    def gen_write_barrier(self, regalloc, base_reg, value_reg):
+        pass
 
 # ____________________________________________________________
 
@@ -21,7 +26,7 @@
     moving_gc = False
     gcrootmap = None
 
-    def __init__(self, gcdescr, mixlevelann):
+    def __init__(self, gcdescr, cpu):
         # grab a pointer to the Boehm 'malloc' function
         compilation_info = ExternalCompilationInfo(libraries=['gc'])
         malloc_fn_ptr = rffi.llexternal("GC_malloc",
@@ -220,10 +225,11 @@
 class GcLLDescr_framework(GcLLDescription):
     GcRefList = GcRefList
 
-    def __init__(self, gcdescr, mixlevelann):
+    def __init__(self, gcdescr, cpu):
         from pypy.rpython.memory.gc.base import choose_gc_from_config
         from pypy.rpython.memory.gctransform import framework
-        self.translator = mixlevelann.rtyper.annotator.translator
+        self.cpu = cpu
+        self.translator = cpu.mixlevelann.rtyper.annotator.translator
 
         # to find roots in the assembler, make a GcRootMap
         name = gcdescr.config.translation.gcrootfinder
@@ -243,8 +249,10 @@
             'gcmapstart': lambda: gcrootmap.gcmapstart(),
             'gcmapend': lambda: gcrootmap.gcmapend(),
             }
-        GCClass, _ = choose_gc_from_config(gcdescr.config)
-        self.moving_gc = GCClass.moving_gc
+        self.GCClass, _ = choose_gc_from_config(gcdescr.config)
+        self.moving_gc = self.GCClass.moving_gc
+        self.HDRPTR = lltype.Ptr(self.GCClass.HDR)
+        self.fielddescr_tid = cpu.fielddescrof(self.GCClass.HDR, 'tid')
 
         # make a malloc function, with three arguments
         def malloc_basic(size, type_id, has_finalizer):
@@ -254,6 +262,8 @@
         self.malloc_basic = malloc_basic
         self.GC_MALLOC_BASIC = lltype.Ptr(lltype.FuncType(
             [lltype.Signed, lltype.Signed, lltype.Bool], llmemory.GCREF))
+        self.WB_FUNCPTR = lltype.Ptr(lltype.FuncType(
+            [llmemory.Address, llmemory.Address], lltype.Void))
 
     def sizeof(self, S, translate_support_code):
         from pypy.rpython.memory.gctypelayout import weakpointer_offset
@@ -285,9 +295,52 @@
     def get_funcptr_for_new(self):
         return llhelper(self.GC_MALLOC_BASIC, self.malloc_basic)
 
+    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)
+        if hdr.tid & self.GCClass.JIT_WB_IF_FLAG:
+            # get a pointer to the 'remember_young_pointer' function from
+            # the GC, and call it immediately
+            funcptr = llop.get_write_barrier_failing_case(self.WB_FUNCPTR)
+            funcptr(llmemory.cast_ptr_to_adr(gcref_struct),
+                    llmemory.cast_ptr_to_adr(gcref_newptr))
+
+    def gen_write_barrier(self, assembler, base_reg, value_reg):
+        assert isinstance(base_reg, REG)
+        assert isinstance(value_reg, REG)
+        # XXX very low-level, needs fixing if anything changes :-/
+        assembler.mc.TEST(mem(base_reg, 0), imm32(self.GCClass.JIT_WB_IF_FLAG))
+        assembler.mc.write('\x74\x0B')         # JZ label_end
+        # xxx longish - save all three registers in REGS; we know that base_reg
+        # and value_reg are two of these registers, find out the missing one
+        if base_reg is eax:
+            if value_reg is ecx:   third_reg = edx
+            elif value_reg is edx: third_reg = ecx
+            else: assert 0, "bad value_reg"
+        elif base_reg is ecx:
+            if value_reg is edx:   third_reg = eax
+            elif value_reg is eax: third_reg = edx
+            else: assert 0, "bad value_reg"
+        elif base_reg is edx:
+            if value_reg is eax:   third_reg = ecx
+            elif value_reg is ecx: third_reg = eax
+            else: assert 0, "bad value_reg"
+        else:
+            assert 0, "bad base_reg"
+        assembler.mc.PUSH(third_reg)           # 1 byte
+        assembler.mc.PUSH(value_reg)           # 1 byte
+        assembler.mc.PUSH(base_reg)            # 1 byte
+        funcptr = llop.get_write_barrier_failing_case(self.WB_FUNCPTR)
+        funcaddr = rffi.cast(lltype.Signed, funcptr)
+        assembler.mc.CALL(rel32(funcaddr))     # 5 bytes
+        assembler.mc.POP(base_reg)             # 1 byte
+        assembler.mc.POP(value_reg)            # 1 byte
+        assembler.mc.POP(third_reg)            # 1 byte
+                                       # total: 11 bytes
+
 # ____________________________________________________________
 
-def get_ll_description(gcdescr, mixlevelann):
+def get_ll_description(gcdescr, cpu):
     if gcdescr is not None:
         name = gcdescr.config.translation.gctransformer
     else:
@@ -297,4 +350,4 @@
     except KeyError:
         raise NotImplementedError("GC transformer %r not supported by "
                                   "the x86 backend" % (name,))
-    return cls(gcdescr, mixlevelann)
+    return cls(gcdescr, cpu)

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	Mon Jun  1 18:31:10 2009
@@ -1001,16 +1001,22 @@
 
     def _unpack_fielddescr(self, fielddescr):
         from pypy.jit.backend.x86.runner import CPU386
-        ofs, size, _ = CPU386.unpack_fielddescr(fielddescr)
-        return imm(ofs), imm(size)
+        ofs, size, ptr = CPU386.unpack_fielddescr(fielddescr)
+        return imm(ofs), imm(size), ptr
 
     def consider_setfield_gc(self, op, ignored):
         base_loc = self.make_sure_var_in_reg(op.args[0], op.args)
-        ofs_loc, size_loc = self._unpack_fielddescr(op.descr)
         value_loc = self.make_sure_var_in_reg(op.args[1], op.args)
+        ofs_loc, size_loc, ptr = self._unpack_fielddescr(op.descr)
+        if ptr:
+            gc_ll_descr = self.assembler.cpu.gc_ll_descr
+            gc_ll_descr.gen_write_barrier(self.assembler, base_loc, value_loc)
         self.eventually_free_vars(op.args)
         self.PerformDiscard(op, [base_loc, ofs_loc, size_loc, value_loc])
 
+    #def consider_setfield_raw(...):
+    #    like consider_setfield_gc(), except without write barrier support
+
     def consider_strsetitem(self, op, ignored):
         base_loc = self.make_sure_var_in_reg(op.args[0], op.args)
         ofs_loc = self.make_sure_var_in_reg(op.args[1], op.args)
@@ -1030,7 +1036,7 @@
                                  imm(scale), imm(ofs)])
 
     def consider_getfield_gc(self, op, ignored):
-        ofs_loc, size_loc = self._unpack_fielddescr(op.descr)
+        ofs_loc, size_loc, _ = self._unpack_fielddescr(op.descr)
         base_loc = self.make_sure_var_in_reg(op.args[0], op.args)
         self.eventually_free_vars(op.args)
         result_loc = self.force_allocate_reg(op.result, [])

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	Mon Jun  1 18:31:10 2009
@@ -103,8 +103,8 @@
         self._setup_prebuilt_error('ovf', OverflowError)
         self._setup_prebuilt_error('zer', ZeroDivisionError)
         self.generated_mps = r_dict(const_descr_eq, const_descr_hash)
-        self.gc_ll_descr = get_ll_description(gcdescr, mixlevelann)
         self._descr_caches = {}
+        self.gc_ll_descr = get_ll_description(gcdescr, self)
         self.vtable_offset, _ = symbolic.get_field_token(rclass.OBJECT,
                                                          'typeptr',
                                                         translate_support_code)
@@ -504,11 +504,13 @@
             v = rffi.cast(rffi.USHORT, vbox.getint())
             rffi.cast(rffi.CArrayPtr(rffi.USHORT), gcref)[ofs/2] = v
         elif size == WORD:
-            a = rffi.cast(rffi.CArrayPtr(lltype.Signed), gcref)
             if ptr:
                 ptr = vbox.getptr(llmemory.GCREF)
+                self.gc_ll_descr.do_write_barrier(gcref, ptr)
+                a = rffi.cast(rffi.CArrayPtr(lltype.Signed), gcref)
                 a[ofs/WORD] = self.cast_gcref_to_int(ptr)
             else:
+                a = rffi.cast(rffi.CArrayPtr(lltype.Signed), gcref)
                 a[ofs/WORD] = vbox.getint()
         else:
             raise NotImplementedError("size = %d" % size)



More information about the Pypy-commit mailing list