[pypy-svn] r70956 - in pypy/branch/gc-huge-list/pypy/jit/backend: test x86 x86/test

arigo at codespeak.net arigo at codespeak.net
Thu Jan 28 18:07:55 CET 2010


Author: arigo
Date: Thu Jan 28 18:07:54 2010
New Revision: 70956

Modified:
   pypy/branch/gc-huge-list/pypy/jit/backend/test/runner_test.py
   pypy/branch/gc-huge-list/pypy/jit/backend/x86/assembler.py
   pypy/branch/gc-huge-list/pypy/jit/backend/x86/regalloc.py
   pypy/branch/gc-huge-list/pypy/jit/backend/x86/test/test_gc_integration.py
Log:
(arigo, fijal)
Implement the new write barrier for JIT's x86 backend.


Modified: pypy/branch/gc-huge-list/pypy/jit/backend/test/runner_test.py
==============================================================================
--- pypy/branch/gc-huge-list/pypy/jit/backend/test/runner_test.py	(original)
+++ pypy/branch/gc-huge-list/pypy/jit/backend/test/runner_test.py	Thu Jan 28 18:07:54 2010
@@ -1261,14 +1261,17 @@
         self.cpu.clear_exception()
 
     def test_cond_call_gc_wb(self):
-        def func_void(a, b):
-            record.append((a, b))
+        def func_void(a, b, c):
+            record.append((a, b, c))
         record = []
         #
-        FUNC = self.FuncType([lltype.Signed, lltype.Signed], lltype.Void)
+        FUNC = self.FuncType([lltype.Signed, lltype.Signed, lltype.Signed],
+                             lltype.Void)
         func_ptr = llhelper(lltype.Ptr(FUNC), func_void)
         funcbox = self.get_funcbox(self.cpu, func_ptr)
         calldescr = self.cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT)
+        T = lltype.GcStruct('T', ('name', lltype.Signed))
+        fielddescr = self.cpu.fielddescrof(T, 'name')
         for cond in [False, True]:
             value = random.randrange(-sys.maxint, sys.maxint)
             if cond:
@@ -1278,10 +1281,42 @@
             del record[:]
             self.execute_operation(rop.COND_CALL_GC_WB,
                                    [BoxInt(value), ConstInt(4096),
-                                    funcbox, BoxInt(655360), BoxInt(-2121)],
+                                    funcbox, BoxInt(655360), BoxInt(-2121),
+                                    fielddescr],
+                                   'void', descr=calldescr)
+            if cond:
+                assert record == [(655360, -2121, fielddescr.offset)]
+            else:
+                assert record == []
+
+    def test_cond_call_gc_wb_array(self):
+        def func_void(a, b, c):
+            record.append((a, b, c))
+        record = []
+        #
+        FUNC = self.FuncType([lltype.Signed, lltype.Signed, lltype.Signed],
+                             lltype.Void)
+        func_ptr = llhelper(lltype.Ptr(FUNC), func_void)
+        funcbox = self.get_funcbox(self.cpu, func_ptr)
+        calldescr = self.cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT)
+        A = lltype.GcArray(lltype.Signed)
+        arraydescr = self.cpu.arraydescrof(A)
+        for cond in [False, True]:
+            value = random.randrange(-sys.maxint, sys.maxint)
+            if cond:
+                value |= 4096
+            else:
+                value &= ~4096
+            del record[:]
+            self.execute_operation(rop.COND_CALL_GC_WB_ARRAY,
+                                   [BoxInt(value), ConstInt(4096),
+                                    funcbox, BoxInt(655360), BoxInt(-2121),
+                                    arraydescr, BoxInt(3)],
                                    'void', descr=calldescr)
             if cond:
-                assert record == [(655360, -2121)]
+                offset = arraydescr.get_base_size(False)
+                size = arraydescr.get_item_size(False)
+                assert record == [(655360, -2121, offset + size * 3)]
             else:
                 assert record == []
 

Modified: pypy/branch/gc-huge-list/pypy/jit/backend/x86/assembler.py
==============================================================================
--- pypy/branch/gc-huge-list/pypy/jit/backend/x86/assembler.py	(original)
+++ pypy/branch/gc-huge-list/pypy/jit/backend/x86/assembler.py	Thu Jan 28 18:07:54 2010
@@ -413,7 +413,10 @@
                                          resloc, current_depths)
 
     def load_effective_addr(self, sizereg, baseofs, scale, result):
-        self.mc.LEA(result, addr_add(imm(0), sizereg, baseofs, scale))
+        self.mc.LEA(result, self.effective_addr(sizereg, baseofs, scale))
+
+    def effective_addr(self, sizereg, baseofs, scale):
+        return addr_add(imm(0), sizereg, baseofs, scale)
 
     def _unaryop(asmop):
         def genop_unary(self, op, arglocs, resloc):
@@ -1307,6 +1310,12 @@
         return self.implement_guard(addr, self.mc.JL)        
 
     def genop_discard_cond_call_gc_wb(self, op, arglocs):
+        self._cond_call_gc_wb(op, arglocs, False)
+
+    def genop_discard_cond_call_gc_wb_array(self, op, arglocs):
+        self._cond_call_gc_wb(op, arglocs, True)
+
+    def _cond_call_gc_wb(self, op, arglocs, is_array):
         # use 'mc._mc' directly instead of 'mc', to avoid
         # bad surprizes if the code buffer is mostly full
         loc_cond = arglocs[0]
@@ -1317,8 +1326,29 @@
         jz_location = mc.get_relative_pos()
         # the following is supposed to be the slow path, so whenever possible
         # we choose the most compact encoding over the most efficient one.
-        for i in range(len(arglocs)-1, 2, -1):
+        # At this point, arglocs is:
+        #    [cond, mask, fn, arg1, arg2, arg3, regs_to_save_and_restore....]
+        # except that arg3 needs to be replaced by "LEA reg, arg3" if is_array.
+        # First push regs_to_save_and_restore
+        for i in range(len(arglocs)-1, 5, -1):
             mc.PUSH(arglocs[i])
+        # Push arg3 or the result of "LEA reg, arg3"
+        if not is_array:
+            mc.PUSH(arglocs[5])
+        else:
+            # We need a free register in (eax, ecx, edx)
+            # which is not arglocs[3] or arglocs[4]
+            tmpreg = eax
+            if tmpreg is arglocs[3] or tmpreg is arglocs[4]:
+                tmpreg = ecx
+                if tmpreg is arglocs[3] or tmpreg is arglocs[4]:
+                    tmpreg = edx
+            mc.LEA(tmpreg, arglocs[5])
+            mc.PUSH(tmpreg)
+        # Push arg2 and arg1
+        mc.PUSH(arglocs[4])
+        mc.PUSH(arglocs[3])
+        # Done pushing arguments...
         mc.CALL(rel32(op.args[2].getint()))
         pop_count = 0
         for i in range(3, len(arglocs)):

Modified: pypy/branch/gc-huge-list/pypy/jit/backend/x86/regalloc.py
==============================================================================
--- pypy/branch/gc-huge-list/pypy/jit/backend/x86/regalloc.py	(original)
+++ pypy/branch/gc-huge-list/pypy/jit/backend/x86/regalloc.py	Thu Jan 28 18:07:54 2010
@@ -655,7 +655,15 @@
         
     def consider_cond_call_gc_wb(self, op):
         assert op.result is None
-        arglocs = [self.loc(arg) for arg in op.args]
+        arglocs = []
+        for i in range(len(op.args) - 1):
+            arglocs.append(self.loc(op.args[i]))
+        descr = op.args[-1]
+        ofsloc = self._unpack_fielddescr(descr)[0]
+        arglocs.append(ofsloc)
+        self._call_wb_common(op, arglocs, 1)
+
+    def _call_wb_common(self, op, arglocs, toignore):
         # add eax, ecx and edx as extra "arguments" to ensure they are
         # saved and restored.  Fish in self.rm to know which of these
         # registers really need to be saved (a bit of a hack).  Moreover,
@@ -668,7 +676,21 @@
                 and reg not in arglocs[3:]):
                 arglocs.append(reg)
         self.PerformDiscard(op, arglocs)
-        self.rm.possibly_free_vars(op.args)
+        for i in range(len(op.args) - toignore):
+            self.rm.possibly_free_var(op.args[i])
+
+    def consider_cond_call_gc_wb_array(self, op):
+        assert op.result is None
+        arglocs = []
+        index = op.args[-1]
+        index_loc = self.make_sure_var_in_reg(index)
+        for i in range(len(op.args) - 2):
+            arglocs.append(self.loc(op.args[i]))
+        descr = op.args[-2]
+        scale, ofs, ptr = self._unpack_arraydescr(descr)
+        arglocs.append(self.assembler.effective_addr(index_loc, ofs, scale))
+        self._call_wb_common(op, arglocs, 2)
+        self.rm.possibly_free_var(index)
 
     def _fastpath_malloc(self, op, descr):
         assert isinstance(descr, BaseSizeDescr)

Modified: pypy/branch/gc-huge-list/pypy/jit/backend/x86/test/test_gc_integration.py
==============================================================================
--- pypy/branch/gc-huge-list/pypy/jit/backend/x86/test/test_gc_integration.py	(original)
+++ pypy/branch/gc-huge-list/pypy/jit/backend/x86/test/test_gc_integration.py	Thu Jan 28 18:07:54 2010
@@ -285,3 +285,5 @@
         assert gc_ll_descr.nursery[1] == self.vtable_int
         nurs_adr = rffi.cast(lltype.Signed, gc_ll_descr.nursery)
         assert gc_ll_descr.addrs[0] == nurs_adr + 8
+
+



More information about the Pypy-commit mailing list