Author: Armin Rigo <[email protected]>
Branch: emit-call-x86
Changeset: r64329:5b914c5dd93e
Date: 2013-05-19 17:43 +0200
http://bitbucket.org/pypy/pypy/changeset/5b914c5dd93e/

Log:    A first version of the code specifically for call_release_gil on
        x86-64.

diff --git a/rpython/jit/backend/x86/callbuilder.py 
b/rpython/jit/backend/x86/callbuilder.py
--- a/rpython/jit/backend/x86/callbuilder.py
+++ b/rpython/jit/backend/x86/callbuilder.py
@@ -86,9 +86,10 @@
             self.current_esp += self._fix_stdcall(self.callconv)
 
     def subtract_esp_aligned(self, count):
-        align = align_stack_words(count)
-        self.current_esp -= align * WORD
-        self.mc.SUB_ri(esp.value, align * WORD)
+        if count > 0:
+            align = align_stack_words(count)
+            self.current_esp -= align * WORD
+            self.mc.SUB_ri(esp.value, align * WORD)
 
     def restore_esp(self, target_esp=0):
         if self.current_esp != target_esp:
@@ -143,12 +144,8 @@
         self.asm.pop_gcmap(self.mc)
 
     def call_releasegil_addr_and_move_real_arguments(self):
-        if IS_X86_32 and self.asm._is_asmgcc():
-            needs_extra_esp = 1      # only for asmgcc on x86_32
-        else:
-            needs_extra_esp = 0
         initial_esp = self.current_esp
-        self.save_register_arguments(needs_extra_esp)
+        self.save_register_arguments()
         #
         if not self.asm._is_asmgcc():
             # the helper takes no argument
@@ -182,6 +179,7 @@
             # Call the closestack() function (also releasing the GIL)
             # with 'reg' as argument
             if IS_X86_32:
+                self.subtract_esp_aligned(1)
                 self.mc.MOV_sr(0, reg.value)
             #else:
             #   on x86_64, reg is edi so that it is already correct
@@ -191,10 +189,8 @@
         self.restore_register_arguments()
         self.restore_esp(initial_esp)
 
-    def save_register_arguments(self, needs_extra_esp):
+    def save_register_arguments(self):
         """Overridden in CallBuilder64"""
-        if needs_extra_esp:
-            self.subtract_esp_aligned(needs_extra_esp)
 
     def restore_register_arguments(self):
         """Overridden in CallBuilder64"""
@@ -241,8 +237,7 @@
         for i in range(n):
             loc = arglocs[i]
             stack_depth += loc.get_width() // WORD
-        if stack_depth > self.stack_max:
-            self.subtract_esp_aligned(stack_depth - self.stack_max)
+        self.subtract_esp_aligned(stack_depth - self.stack_max)
         #
         p = 0
         for i in range(n):
@@ -333,13 +328,17 @@
 
     ARGUMENTS_GPR = [edi, esi, edx, ecx, r8, r9]
     ARGUMENTS_XMM = [xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7]
+    DONT_MOVE_GPR = []
+    _ALL_CALLEE_SAVE_GPR = [ebx, r12, r13, r14, r15]
 
     next_arg_gpr = 0
     next_arg_xmm = 0
 
-    def _unused_gpr(self):
+    def _unused_gpr(self, hint):
         i = self.next_arg_gpr
         self.next_arg_gpr = i + 1
+        if hint in self.DONT_MOVE_GPR:
+            return hint
         try:
             return self.ARGUMENTS_GPR[i]
         except IndexError:
@@ -354,13 +353,19 @@
             return None
 
     def _permute_to_prefer_unused_registers(self, lst):
+        # permute 'lst' so that it starts with registers that are not
+        # in 'self.already_used', and ends with registers that are.
         N = len(lst)
-        for i in range(N - 1):
+        i = 0
+        while i < N:
             reg = lst[i]
             if reg in self.already_used:
-                for j in range(i, N - 1):        # move reg to the end
-                    lst[j] = lst[j + 1]
-                lst[N - 1] = reg
+                # move this reg to the end, and decrement N
+                N -= 1
+                assert N >= i
+                lst[N], lst[i] = lst[i], lst[N]
+            else:
+                i += 1
 
     def select_call_release_gil_mode(self):
         AbstractCallBuilder.select_call_release_gil_mode(self)
@@ -376,9 +381,11 @@
         lst = X86_64_RegisterManager.save_around_call_regs[:]
         self._permute_to_prefer_unused_registers(lst)
         self.ARGUMENTS_GPR = lst[:len(self.ARGUMENTS_GPR)]
+        self.DONT_MOVE_GPR = self._ALL_CALLEE_SAVE_GPR
         #
         lst = [xmm0, xmm1, xmm2, xmm3, xmm4, xmm5, xmm6, xmm7]
         self._permute_to_prefer_unused_registers(lst)
+        assert len(lst) == len(self.ARGUMENTS_XMM)
         self.ARGUMENTS_XMM = lst
 
     def prepare_arguments(self):
@@ -411,7 +418,7 @@
                     on_stack += 1
                 singlefloats.append((loc, tgt))
             else:
-                tgt = self._unused_gpr()
+                tgt = self._unused_gpr(hint=loc)
                 if tgt is None:
                     tgt = RawEspLoc(on_stack * WORD, INT)
                     on_stack += 1
@@ -429,8 +436,7 @@
                            + max(floats - len(self.ARGUMENTS_XMM), 0))
             assert stack_depth == on_stack
 
-        if on_stack > self.stack_max:
-            self.subtract_esp_aligned(on_stack - self.stack_max)
+        self.subtract_esp_aligned(on_stack - self.stack_max)
 
         # Handle register arguments: first remap the xmm arguments
         remap_frame_layout(self.asm, xmm_src_locs, xmm_dst_locs,
@@ -490,11 +496,45 @@
             type = INT
         self.tmpresloc = RawEspLoc(0, type)
 
-    def save_register_arguments(self, needs_extra_esp):
-        xxx
+    def save_register_arguments(self):
+        # Save the argument registers, which are given by self.ARGUMENTS_xxx.
+        n_gpr = min(self.next_arg_gpr, len(self.ARGUMENTS_GPR))
+        n_xmm = min(self.next_arg_xmm, len(self.ARGUMENTS_XMM))
+        n_saved_regs = n_gpr + n_xmm
+        for i in range(n_gpr):
+            if self.ARGUMENTS_GPR[i] in self._ALL_CALLEE_SAVE_GPR:
+                n_saved_regs -= 1     # don't need to save it
+        self.subtract_esp_aligned(n_saved_regs)
+        #
+        n = 0
+        for i in range(n_gpr):
+            if self.ARGUMENTS_GPR[i] not in self._ALL_CALLEE_SAVE_GPR:
+                self.mc.MOV_sr(n * WORD, self.ARGUMENTS_GPR[i].value)
+                n += 1
+        for i in range(n_xmm):
+            self.mc.MOVSD_sx(n * WORD, self.ARGUMENTS_XMM[i].value)
+            n += 1
+        assert n == n_saved_regs
+        self.n_saved_regs = n_saved_regs
 
     def restore_register_arguments(self):
-        xxx
+        # Restore the saved values into the *real* registers used for calls
+        # --- which are not self.ARGUMENTS_xxx!
+        n_gpr = min(self.next_arg_gpr, len(self.ARGUMENTS_GPR))
+        n_xmm = min(self.next_arg_xmm, len(self.ARGUMENTS_XMM))
+        #
+        n = 0
+        for i in range(n_gpr):
+            tgtvalue = CallBuilder64.ARGUMENTS_GPR[i].value
+            if self.ARGUMENTS_GPR[i] not in self._ALL_CALLEE_SAVE_GPR:
+                self.mc.MOV_rs(tgtvalue, n * WORD)
+                n += 1
+            else:
+                self.mc.MOV_rr(tgtvalue, self.ARGUMENTS_GPR[i].value)
+        for i in range(n_xmm):
+            self.mc.MOVSD_xs(CallBuilder64.ARGUMENTS_XMM[i].value, n * WORD)
+            n += 1
+        assert n == self.n_saved_regs
 
 
 if IS_X86_32:
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to