Author: Armin Rigo <[email protected]>
Branch: 
Changeset: r63374:154e81a46200
Date: 2013-04-15 17:50 +0200
http://bitbucket.org/pypy/pypy/changeset/154e81a46200/

Log:    Clean up the number and significance of the various flags
        "can_collect", "reload_frame" etc. and hopefully fix asmgcc.

diff --git a/rpython/jit/backend/x86/assembler.py 
b/rpython/jit/backend/x86/assembler.py
--- a/rpython/jit/backend/x86/assembler.py
+++ b/rpython/jit/backend/x86/assembler.py
@@ -112,6 +112,11 @@
         self.float_const_neg_addr = float_constants
         self.float_const_abs_addr = float_constants + 16
 
+    def set_extra_stack_depth(self, mc, value):
+        if self._is_asmgcc():
+            extra_ofs = self.cpu.get_ofs_of_frame_field('jf_extra_stack_depth')
+            mc.MOV_bi(extra_ofs, value)
+
     def build_frame_realloc_slowpath(self):
         mc = codebuf.MachineCodeBlockWrapper()
         self._push_all_regs_to_frame(mc, [], self.cpu.supports_floats)
@@ -134,16 +139,14 @@
             mc.MOV_sr(0, ebp.value)
         # align
 
-        extra_ofs = self.cpu.get_ofs_of_frame_field('jf_extra_stack_depth')
-        mc.MOV_bi(extra_ofs, align * WORD)
+        self.set_extra_stack_depth(mc, align * WORD)
         self._store_and_reset_exception(mc, None, ebx, ecx)
 
         mc.CALL(imm(self.cpu.realloc_frame))
         mc.MOV_rr(ebp.value, eax.value)
         self._restore_exception(mc, None, ebx, ecx)
         mc.ADD_ri(esp.value, (align - 1) * WORD)
-        mc.MOV_bi(extra_ofs, 0)
-
+        self.set_extra_stack_depth(mc, 0)
 
         gcrootmap = self.cpu.gc_ll_descr.gcrootmap
         if gcrootmap and gcrootmap.is_shadow_stack:
@@ -176,8 +179,7 @@
         elif hasattr(self.cpu.gc_ll_descr, 'passes_frame'):
             # for tests only
             mc.MOV_rr(esi.value, ebp.value)
-        extra_ofs = self.cpu.get_ofs_of_frame_field('jf_extra_stack_depth')
-        mc.MOV_bi(extra_ofs, 16)
+        self.set_extra_stack_depth(mc, 16)
         mc.CALL(imm(addr))
         mc.ADD_ri(esp.value, 16 - WORD)
         mc.TEST_rr(eax.value, eax.value)
@@ -186,7 +188,7 @@
         #
         nursery_free_adr = self.cpu.gc_ll_descr.get_nursery_free_addr()
         self._reload_frame_if_necessary(mc, align_stack=True)
-        mc.MOV_bi(extra_ofs, 0)
+        self.set_extra_stack_depth(mc, 0)
         self._pop_all_regs_from_frame(mc, [eax, edi], self.cpu.supports_floats)
         mc.MOV(edi, heap(nursery_free_adr))   # load this in EDI
         # clear the gc pattern
@@ -973,14 +975,17 @@
         return bool(gcrootmap) and not gcrootmap.is_shadow_stack
 
     def _emit_call(self, x, arglocs, start=0, tmp=eax,
-                   argtypes=None, callconv=FFI_DEFAULT_ABI, can_collect=1,
-                   stack_max=PASS_ON_MY_FRAME, reload_frame=False):
-        if can_collect == 1 and not self._is_asmgcc():
-            can_collect = 2    # don't bother with jf_extra_stack_depth
+                   argtypes=None, callconv=FFI_DEFAULT_ABI,
+                   # whether to worry about a CALL that can collect; this
+                   # is always true except in call_release_gil
+                   can_collect=True,
+                   # max number of arguments we can pass on esp; if more,
+                   # we need to decrease esp temporarily
+                   stack_max=PASS_ON_MY_FRAME):
+        #
         if IS_X86_64:
             return self._emit_call_64(x, arglocs, start, argtypes,
-                                      can_collect, stack_max,
-                                      reload_frame=reload_frame)
+                                      can_collect, stack_max)
         stack_depth = 0
         n = len(arglocs)
         for i in range(start, n):
@@ -989,9 +994,8 @@
         if stack_depth > stack_max:
             align = align_stack_words(stack_depth - stack_max)
             self.mc.SUB_ri(esp.value, align * WORD)
-            if can_collect == 1:
-                ofs = self.cpu.get_ofs_of_frame_field('jf_extra_stack_depth')
-                self.mc.MOV_bi(ofs, align * WORD)
+            if can_collect:
+                self.set_extra_stack_depth(self.mc, align * WORD)
         else:
             align = 0
         p = 0
@@ -1016,23 +1020,24 @@
             p += loc.get_width()
         # x is a location
         if can_collect:
+            # we push *now* the gcmap, describing the status of GC registers
+            # after the rearrangements done just above, ignoring the return
+            # value eax, if necessary
             noregs = self.cpu.gc_ll_descr.is_shadow_stack()
             gcmap = self._regalloc.get_gcmap([eax], noregs=noregs)
             self.push_gcmap(self.mc, gcmap, store=True)
+        #
         self.mc.CALL(x)
         if callconv != FFI_DEFAULT_ABI:
             self._fix_stdcall(callconv, p - align * WORD)
         elif align:
             self.mc.ADD_ri(esp.value, align * WORD)
+        #
         if can_collect:
-            self._reload_frame_if_necessary(self.mc, can_collect=can_collect)
-            if align and can_collect == 1:
-                ofs = self.cpu.get_ofs_of_frame_field('jf_extra_stack_depth')
-                self.mc.MOV_bi(ofs, 0)
+            self._reload_frame_if_necessary(self.mc)
+            if align:
+                self.set_extra_stack_depth(self.mc, 0)
             self.pop_gcmap(self.mc)
-        elif reload_frame:
-            self._reload_frame_if_necessary(self.mc)
-        #
 
     def _fix_stdcall(self, callconv, p):
         from rpython.rlib.clibffi import FFI_STDCALL
@@ -1042,7 +1047,7 @@
         self.mc.SUB_ri(esp.value, p)
 
     def _emit_call_64(self, x, arglocs, start, argtypes,
-                      can_collect, stack_max, reload_frame=False):
+                      can_collect, stack_max):
         src_locs = []
         dst_locs = []
         xmm_src_locs = []
@@ -1066,9 +1071,8 @@
         align = 0
         if stack_depth > stack_max:
             align = align_stack_words(stack_depth - stack_max)
-            if can_collect == 1:
-                ofs = self.cpu.get_ofs_of_frame_field('jf_extra_stack_depth')
-                self.mc.MOV_bi(ofs, align * WORD)
+            if can_collect:
+                self.set_extra_stack_depth(self.mc, align * WORD)
             self.mc.SUB_ri(esp.value, align * WORD)
         for i in range(start, len(arglocs)):
             loc = arglocs[i]
@@ -1123,35 +1127,30 @@
             x = r10
         remap_frame_layout(self, src_locs, dst_locs, X86_64_SCRATCH_REG)
         if can_collect:
+            # we push *now* the gcmap, describing the status of GC registers
+            # after the rearrangements done just above, ignoring the return
+            # value eax, if necessary
             noregs = self.cpu.gc_ll_descr.is_shadow_stack()
             gcmap = self._regalloc.get_gcmap([eax], noregs=noregs)
             self.push_gcmap(self.mc, gcmap, store=True)
+        #
         self.mc.CALL(x)
-        if can_collect:
-            self._reload_frame_if_necessary(self.mc, can_collect=can_collect)
-            if align and can_collect == 1:
-                ofs = self.cpu.get_ofs_of_frame_field('jf_extra_stack_depth')
-                self.mc.MOV_bi(ofs, 0)
-        elif reload_frame:
-            self._reload_frame_if_necessary(self.mc)
         if align:
             self.mc.ADD_ri(esp.value, align * WORD)
+        #
         if can_collect:
+            self._reload_frame_if_necessary(self.mc)
+            if align:
+                self.set_extra_stack_depth(self.mc, 0)
             self.pop_gcmap(self.mc)
 
-    def _reload_frame_if_necessary(self, mc, align_stack=False, can_collect=0):
+    def _reload_frame_if_necessary(self, mc, align_stack=False):
         gcrootmap = self.cpu.gc_ll_descr.gcrootmap
         if gcrootmap:
             if gcrootmap.is_shadow_stack:
                 rst = gcrootmap.get_root_stack_top_addr()
                 mc.MOV(ecx, heap(rst))
                 mc.MOV(ebp, mem(ecx, -WORD))
-            elif can_collect == 3:
-                # specially for call_release_gil: must reload ebp from the css
-                from rpython.memory.gctransform import asmgcroot
-                css = WORD * (PASS_ON_MY_FRAME - asmgcroot.JIT_USE_WORDS)
-                index_of_ebp = css + WORD * (2+asmgcroot.INDEX_OF_EBP)
-                mc.MOV_rs(ebp.value, index_of_ebp)  # MOV EBP, [css.ebp]
         wbdescr = self.cpu.gc_ll_descr.write_barrier_descr
         if gcrootmap and wbdescr:
             # frame never uses card marking, so we enforce this is not
@@ -1950,12 +1949,9 @@
             if self._is_asmgcc():
                 from rpython.memory.gctransform import asmgcroot
                 stack_max -= asmgcroot.JIT_USE_WORDS
-                can_collect = 3    # asmgcc only: don't write 
jf_extra_stack_depth,
-                                   # and reload ebp from the css
-            else:
-                can_collect = 0
+            can_collect = False
         else:
-            can_collect = 1
+            can_collect = True
 
         self._emit_call(x, arglocs, 3, tmp=tmp,
                         argtypes=descr.get_arg_types(),
@@ -2022,8 +2018,13 @@
         # first, close the stack in the sense of the asmgcc GC root tracker
         gcrootmap = self.cpu.gc_ll_descr.gcrootmap
         if gcrootmap:
-            noregs = self.cpu.gc_ll_descr.is_shadow_stack()
-            gcmap = self._regalloc.get_gcmap([eax], noregs=noregs)
+            # we put the gcmap now into the frame before releasing the GIL,
+            # and pop it below after reacquiring the GIL.  The assumption
+            # is that this gcmap describes correctly the situation at any
+            # point in-between: all values containing GC pointers should
+            # be safely saved out of registers by now, and will not be
+            # manipulated by any of the following CALLs.
+            gcmap = self._regalloc.get_gcmap(noregs=True)
             self.push_gcmap(self.mc, gcmap, store=True)
             self.call_release_gil(gcrootmap, arglocs)
         # do the call
@@ -2031,6 +2032,7 @@
         # then reopen the stack
         if gcrootmap:
             self.call_reacquire_gil(gcrootmap, result_loc)
+            self.pop_gcmap(self.mc)     # remove the gcmap saved above
         # finally, the guard_not_forced
         self._emit_guard_not_forced(guard_token)
 
@@ -2059,8 +2061,7 @@
             # Set up jf_extra_stack_depth to pretend that the return address
             # was at css, and so our stack frame is supposedly shorter by
             # (css+WORD) bytes
-            extra_ofs = self.cpu.get_ofs_of_frame_field('jf_extra_stack_depth')
-            self.mc.MOV_bi(extra_ofs, -css-WORD)
+            self.set_extra_stack_depth(self.mc, -css-WORD)
             # Call the closestack() function (also releasing the GIL)
             args = [reg]
         #
@@ -2075,19 +2076,29 @@
         # call the reopenstack() function (also reacquiring the GIL)
         if gcrootmap.is_shadow_stack:
             args = []
+            css = 0
         else:
             from rpython.memory.gctransform import asmgcroot
             css = WORD * (PASS_ON_MY_FRAME - asmgcroot.JIT_USE_WORDS)
-            extra_ofs = self.cpu.get_ofs_of_frame_field('jf_extra_stack_depth')
-            self.mc.MOV_bi(extra_ofs, 0)
             if IS_X86_32:
                 reg = eax
             elif IS_X86_64:
                 reg = edi
             self.mc.LEA_rs(reg.value, css)
             args = [reg]
-        self._emit_call(imm(self.reacqgil_addr), args, can_collect=False,
-                        reload_frame=True)
+        self._emit_call(imm(self.reacqgil_addr), args, can_collect=False)
+        #
+        # Now that we required the GIL, we can reload a possibly modified ebp
+        if not gcrootmap.is_shadow_stack:
+            # special-case: reload ebp from the css
+            from rpython.memory.gctransform import asmgcroot
+            index_of_ebp = css + WORD * (2+asmgcroot.INDEX_OF_EBP)
+            mc.MOV_rs(ebp.value, index_of_ebp)  # MOV EBP, [css.ebp]
+        #else:
+        #   for shadowstack, done for us by _reload_frame_if_necessary()
+        self._reload_frame_if_necessary(self.mc)
+        self.set_extra_stack_depth(self.mc, 0)
+        #
         # restore the result from the stack
         if isinstance(save_loc, RegLoc) and not save_loc.is_xmm:
             self.mc.MOV_rs(save_loc.value, WORD)
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to