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

arigo at codespeak.net arigo at codespeak.net
Wed Jun 3 16:34:34 CEST 2009


Author: arigo
Date: Wed Jun  3 16:34:31 2009
New Revision: 65558

Modified:
   pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/assembler.py
   pypy/branch/pyjitpl5-experiments/pypy/jit/backend/x86/gc.py
Log:
Fix gen_write_barrier().  Still tracking a bug...


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	Wed Jun  3 16:34:31 2009
@@ -42,9 +42,6 @@
     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	Wed Jun  3 16:34:31 2009
@@ -5,7 +5,7 @@
 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, mem, imm32, rel32
+from pypy.jit.backend.x86.ri386 import MODRM, IMM32, mem, imm32, rel32, heap
 from pypy.jit.backend.x86.ri386 import REG, eax, ecx, edx
 
 # ____________________________________________________________
@@ -306,37 +306,51 @@
                     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"
+        from pypy.jit.backend.x86.regalloc import REGS
+        SAVE_ME = [reg for reg in REGS
+                       if reg != base_reg and reg != value_reg]
+        bytes_count = 9 + 2 * len(SAVE_ME)
+        #
+        if isinstance(value_reg, IMM32):
+            if value_reg.value == 0:
+                return      # writing NULL: don't need the write barrier at all
+            bytes_count += 4
         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
+            assert isinstance(value_reg, REG)
+        #
+        if isinstance(base_reg, IMM32):
+            bytes_count += 4
+            tidaddr = heap(base_reg.value + 0)
+        else:
+            assert isinstance(base_reg, REG)
+            tidaddr = mem(base_reg, 0)
+        #
+        assembler.mc.TEST(tidaddr, imm32(self.GCClass.JIT_WB_IF_FLAG))
+        # do the rest using 'mc._mc' directly instead of 'mc', to avoid
+        # bad surprizes if the code buffer is mostly full
+        mc = assembler.mc._mc
+        mc.write('\x74')             # JZ label_end
+        mc.write(chr(bytes_count))
+        start = mc.tell()
+        for reg in SAVE_ME:
+            mc.PUSH(reg)             # len(SAVE_ME) bytes
+        mc.PUSH(value_reg)           # 1 or 5 bytes
+        mc.PUSH(base_reg)            # 1 or 5 bytes
         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
+        mc.CALL(rel32(funcaddr))     # 5 bytes
+        if isinstance(base_reg, REG):
+            mc.POP(base_reg)         # 1 byte
+        else:
+            mc.POP(SAVE_ME[0])
+        if isinstance(value_reg, REG):
+            mc.POP(value_reg)        # 1 byte
+        else:
+            mc.POP(SAVE_ME[0])
+        for i in range(len(SAVE_ME)-1, -1, -1):
+            mc.POP(SAVE_ME[i])       # len(SAVE_ME) bytes
+                              # total: 9+(4?)+(4?)+2*len(SAVE_ME) bytes
+        assert mc.tell() == start + bytes_count
 
 # ____________________________________________________________
 



More information about the Pypy-commit mailing list