[pypy-commit] pypy jitypes2: A saner and more symmetric approach.

Armin Rigo noreply at buildbot.pypy.org
Tue May 31 16:03:41 CEST 2011


Author: Armin Rigo <arigo at tunes.org>
Branch: jitypes2
Changeset: r44613:0ff8b71321d3
Date: 2011-05-31 16:13 +0200
http://bitbucket.org/pypy/pypy/changeset/0ff8b71321d3/

Log:	A saner and more symmetric approach.

diff --git a/pypy/jit/backend/x86/assembler.py b/pypy/jit/backend/x86/assembler.py
--- a/pypy/jit/backend/x86/assembler.py
+++ b/pypy/jit/backend/x86/assembler.py
@@ -129,7 +129,7 @@
             self._build_malloc_slowpath()
         self._build_stack_check_slowpath()
         if gc_ll_descr.gcrootmap:
-            self._build_close_stack(gc_ll_descr.gcrootmap)
+            self._build_release_gil(gc_ll_descr.gcrootmap)
         debug_start('jit-backend-counts')
         self.set_debug(have_debug_prints())
         debug_stop('jit-backend-counts')
@@ -309,7 +309,7 @@
         self.stack_check_slowpath = rawstart
 
     @staticmethod
-    def _close_stack_asmgcc(css):
+    def _release_gil_asmgcc(css):
         # similar to trackgcroot.py:pypy_asm_stackwalk, first part
         from pypy.rpython.memory.gctransform import asmgcroot
         new = rffi.cast(asmgcroot.ASM_FRAMEDATA_HEAD_PTR, css)
@@ -324,7 +324,7 @@
             before()
 
     @staticmethod
-    def _reopen_stack_asmgcc(css):
+    def _reacquire_gil_asmgcc(css):
         # first reacquire the GIL
         after = rffi.aroundstate.after
         if after:
@@ -337,26 +337,35 @@
         prev.next = next
         next.prev = prev
 
+    @staticmethod
+    def _release_gil_shadowstack():
+        before = rffi.aroundstate.before
+        if before:
+            before()
+
+    @staticmethod
+    def _reacquire_gil_shadowstack():
+        after = rffi.aroundstate.after
+        if after:
+            after()
+
     _NOARG_FUNC = lltype.Ptr(lltype.FuncType([], lltype.Void))
     _CLOSESTACK_FUNC = lltype.Ptr(lltype.FuncType([rffi.LONGP],
                                                   lltype.Void))
 
-    def _build_close_stack(self, gcrootmap):
+    def _build_release_gil(self, gcrootmap):
         if gcrootmap.is_shadow_stack:
-            if self.cpu.with_threads:
-                reopenstack_func = llop.gc_adr_of_thread_run_fn(
-                    self._NOARG_FUNC)
-                self.reopenstack_addr = self.cpu.cast_ptr_to_int(
-                    reopenstack_func)
-            else:
-                self.reopenstack_addr = 0
+            releasegil_func = llhelper(self._NOARG_FUNC,
+                                       self._release_gil_shadowstack)
+            reacqgil_func = llhelper(self._NOARG_FUNC,
+                                     self._reacquire_gil_shadowstack)
         else:
-            closestack_func = llhelper(self._CLOSESTACK_FUNC,
-                                       self._close_stack_asmgcc)
-            reopenstack_func = llhelper(self._CLOSESTACK_FUNC,
-                                        self._reopen_stack_asmgcc)
-            self.closestack_addr  = self.cpu.cast_ptr_to_int(closestack_func)
-            self.reopenstack_addr = self.cpu.cast_ptr_to_int(reopenstack_func)
+            releasegil_func = llhelper(self._CLOSESTACK_FUNC,
+                                       self._release_gil_asmgcc)
+            reacqgil_func = llhelper(self._CLOSESTACK_FUNC,
+                                     self._reacquire_gil_asmgcc)
+        self.releasegil_addr  = self.cpu.cast_ptr_to_int(releasegil_func)
+        self.reacqgil_addr = self.cpu.cast_ptr_to_int(reacqgil_func)
 
     def assemble_loop(self, inputargs, operations, looptoken, log):
         '''adds the following attributes to looptoken:
@@ -2042,13 +2051,7 @@
         # first, close the stack in the sense of the asmgcc GC root tracker
         gcrootmap = self.cpu.gc_ll_descr.gcrootmap
         if gcrootmap:
-            # note that regalloc.py used save_all_regs=True to save all
-            # registers, so we don't have to care about saving them (other
-            # than ebp) in the close_stack_struct.  But if they are registers
-            # like %eax that would be destroyed by this call, *and* they are
-            # used by arglocs for the *next* call, then trouble; for now we
-            # will just push/pop them.
-            self.call_close_stack(gcrootmap, arglocs)
+            self.call_release_gil(gcrootmap, arglocs)
         # do the call
         faildescr = guard_op.getdescr()
         fail_index = self.cpu.get_fail_descr_number(faildescr)
@@ -2056,26 +2059,12 @@
         self._genop_call(op, arglocs, result_loc, fail_index)
         # then reopen the stack
         if gcrootmap:
-            self.call_reopen_stack(gcrootmap, result_loc)
+            self.call_reacquire_gil(gcrootmap, result_loc)
         # finally, the guard_not_forced
         self.mc.CMP_bi(FORCE_INDEX_OFS, 0)
         self.implement_guard(guard_token, 'L')
 
-    def call_close_stack(self, gcrootmap, save_registers):
-        if gcrootmap.is_shadow_stack:
-            pass   # no need to close the stack with shadowstack
-        else:
-            self.call_close_stack_asmgcc(save_registers)
-
-    def call_close_stack_asmgcc(self, save_registers):
-        from pypy.rpython.memory.gctransform import asmgcroot
-        css = self._regalloc.close_stack_struct
-        if css == 0:
-            use_words = (2 + max(asmgcroot.INDEX_OF_EBP,
-                                 asmgcroot.FRAME_PTR) + 1)
-            pos = self._regalloc.fm.reserve_location_in_frame(use_words)
-            css = get_ebp_ofs(pos + use_words - 1)
-            self._regalloc.close_stack_struct = css
+    def call_release_gil(self, gcrootmap, save_registers):
         # First, we need to save away the registers listed in
         # 'save_registers' that are not callee-save.  XXX We assume that
         # the XMM registers won't be modified.  We store them in
@@ -2087,21 +2076,41 @@
                 self.mc.MOV_sr(p, reg.value)
                 p += WORD
         self._regalloc.reserve_param(p//WORD)
-        # The location where the future CALL will put its return address
-        # will be [ESP-WORD], so save that as the next frame's top address
-        self.mc.LEA_rs(eax.value, -WORD)        # LEA EAX, [ESP-4]
-        frame_ptr = css + WORD * (2+asmgcroot.FRAME_PTR)
-        self.mc.MOV_br(frame_ptr, eax.value)    # MOV [css.frame], EAX
-        # Save ebp
-        index_of_ebp = css + WORD * (2+asmgcroot.INDEX_OF_EBP)
-        self.mc.MOV_br(index_of_ebp, ebp.value) # MOV [css.ebp], EBP
-        # Call the closestack() function (also releasing the GIL)
-        if IS_X86_32:
-            reg = eax
-        elif IS_X86_64:
-            reg = edi
-        self.mc.LEA_rb(reg.value, css)
-        self._emit_call(-1, imm(self.closestack_addr), [reg])
+        #
+        if gcrootmap.is_shadow_stack:
+            args = []
+        else:
+            # note that regalloc.py used save_all_regs=True to save all
+            # registers, so we don't have to care about saving them (other
+            # than ebp) in the close_stack_struct.  But if they are registers
+            # like %eax that would be destroyed by this call, *and* they are
+            # used by arglocs for the *next* call, then trouble; for now we
+            # will just push/pop them.
+            from pypy.rpython.memory.gctransform import asmgcroot
+            css = self._regalloc.close_stack_struct
+            if css == 0:
+                use_words = (2 + max(asmgcroot.INDEX_OF_EBP,
+                                     asmgcroot.FRAME_PTR) + 1)
+                pos = self._regalloc.fm.reserve_location_in_frame(use_words)
+                css = get_ebp_ofs(pos + use_words - 1)
+                self._regalloc.close_stack_struct = css
+            # The location where the future CALL will put its return address
+            # will be [ESP-WORD], so save that as the next frame's top address
+            self.mc.LEA_rs(eax.value, -WORD)        # LEA EAX, [ESP-4]
+            frame_ptr = css + WORD * (2+asmgcroot.FRAME_PTR)
+            self.mc.MOV_br(frame_ptr, eax.value)    # MOV [css.frame], EAX
+            # Save ebp
+            index_of_ebp = css + WORD * (2+asmgcroot.INDEX_OF_EBP)
+            self.mc.MOV_br(index_of_ebp, ebp.value) # MOV [css.ebp], EBP
+            # Call the closestack() function (also releasing the GIL)
+            if IS_X86_32:
+                reg = eax
+            elif IS_X86_64:
+                reg = edi
+            self.mc.LEA_rb(reg.value, css)
+            args = [reg]
+        #
+        self._emit_call(-1, imm(self.releasegil_addr), args)
         # Finally, restore the registers saved above.
         p = WORD
         for reg in self._regalloc.rm.save_around_call_regs:
@@ -2109,11 +2118,9 @@
                 self.mc.MOV_rs(reg.value, p)
                 p += WORD
 
-    def call_reopen_stack(self, gcrootmap, save_loc):
-        if self.reopenstack_addr == 0:
-            return
+    def call_reacquire_gil(self, gcrootmap, save_loc):
         # save the previous result (eax/xmm0) into the stack temporarily.
-        # XXX like with call_close_stack(), we assume that we don't need
+        # XXX like with call_release_gil(), we assume that we don't need
         # to save xmm0 in this case.
         if isinstance(save_loc, RegLoc) and not save_loc.is_xmm:
             self.mc.MOV_sr(WORD, save_loc.value)
@@ -2130,7 +2137,7 @@
                 reg = edi
             self.mc.LEA_rb(reg.value, css)
             args = [reg]
-        self._emit_call(-1, imm(self.reopenstack_addr), args)
+        self._emit_call(-1, imm(self.reacqgil_addr), args)
         # 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)
diff --git a/pypy/rpython/lltypesystem/lloperation.py b/pypy/rpython/lltypesystem/lloperation.py
--- a/pypy/rpython/lltypesystem/lloperation.py
+++ b/pypy/rpython/lltypesystem/lloperation.py
@@ -491,7 +491,6 @@
     # ^^^ returns an address of pointer, since it can change at runtime
     'gc_adr_of_root_stack_top': LLOp(),
     # ^^^ returns the address of gcdata.root_stack_top (for shadowstack only)
-    'gc_adr_of_thread_run_fn': LLOp(),
 
     # experimental operations in support of thread cloning, only
     # implemented by the Mark&Sweep GC
diff --git a/pypy/rpython/memory/gctransform/framework.py b/pypy/rpython/memory/gctransform/framework.py
--- a/pypy/rpython/memory/gctransform/framework.py
+++ b/pypy/rpython/memory/gctransform/framework.py
@@ -973,12 +973,6 @@
         if hasattr(self.root_walker, 'thread_run_ptr'):
             hop.genop("direct_call", [self.root_walker.thread_run_ptr])
 
-    def gct_gc_adr_of_thread_run_fn(self, hop):
-        assert self.translator.config.translation.thread
-        assert hasattr(self.root_walker, 'thread_run_ptr')
-        hop.genop("same_as", [self.root_walker.thread_run_ptr],
-                  resultvar=hop.spaceop.result)
-
     def gct_gc_thread_start(self, hop):
         assert self.translator.config.translation.thread
         if hasattr(self.root_walker, 'thread_start_ptr'):


More information about the pypy-commit mailing list