Author: Armin Rigo <[email protected]>
Branch: jitypes2
Changeset: r44594:d6a50a20d592
Date: 2011-05-30 19:19 +0200
http://bitbucket.org/pypy/pypy/changeset/d6a50a20d592/

Log:    shadowstack support in CALL_RELEASE_GIL. Much easier than asmgcc.
        Still a bit hard to test correctly at this level...

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()
+            self._build_close_stack(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(css):
+    def _close_stack_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)
@@ -332,7 +332,7 @@
             before()
 
     @staticmethod
-    def _reopen_stack(css):
+    def _reopen_stack_asmgcc(css):
         # first reacquire the GIL
         if css[2]:
             after = rffi.aroundstate.after
@@ -346,16 +346,26 @@
         prev.next = next
         next.prev = prev
 
+    _NOARG_FUNC = lltype.Ptr(lltype.FuncType([], lltype.Void))
     _CLOSESTACK_FUNC = lltype.Ptr(lltype.FuncType([rffi.LONGP],
                                                   lltype.Void))
 
-    def _build_close_stack(self):
-        closestack_func = llhelper(self._CLOSESTACK_FUNC,
-                                   self._close_stack)
-        reopenstack_func = llhelper(self._CLOSESTACK_FUNC,
-                                    self._reopen_stack)
-        self.closestack_addr  = self.cpu.cast_ptr_to_int(closestack_func)
-        self.reopenstack_addr = self.cpu.cast_ptr_to_int(reopenstack_func)
+    def _build_close_stack(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
+        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)
 
     def assemble_loop(self, inputargs, operations, looptoken, log):
         '''adds the following attributes to looptoken:
@@ -2047,7 +2057,7 @@
             # 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(arglocs)
+            self.call_close_stack(gcrootmap, arglocs)
         # do the call
         faildescr = guard_op.getdescr()
         fail_index = self.cpu.get_fail_descr_number(faildescr)
@@ -2055,12 +2065,18 @@
         self._genop_call(op, arglocs, result_loc, fail_index)
         # then reopen the stack
         if gcrootmap:
-            self.call_reopen_stack(result_loc)
+            self.call_reopen_stack(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, save_registers):
+    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:
@@ -2102,7 +2118,9 @@
                 self.mc.MOV_rs(reg.value, p)
                 p += WORD
 
-    def call_reopen_stack(self, save_loc):
+    def call_reopen_stack(self, gcrootmap, save_loc):
+        if self.reopenstack_addr == 0:
+            return
         # save the previous result (eax/xmm0) into the stack temporarily.
         # XXX like with call_close_stack(), we assume that we don't need
         # to save xmm0 in this case.
@@ -2110,14 +2128,18 @@
             self.mc.MOV_sr(WORD, save_loc.value)
             self._regalloc.reserve_param(2)
         # call the reopenstack() function (also reacquiring the GIL)
-        css = self._regalloc.close_stack_struct
-        assert css != 0
-        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.reopenstack_addr), [reg])
+        if gcrootmap.is_shadow_stack:
+            args = []
+        else:
+            css = self._regalloc.close_stack_struct
+            assert css != 0
+            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.reopenstack_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/jit/backend/x86/runner.py b/pypy/jit/backend/x86/runner.py
--- a/pypy/jit/backend/x86/runner.py
+++ b/pypy/jit/backend/x86/runner.py
@@ -22,6 +22,7 @@
 
     BOOTSTRAP_TP = lltype.FuncType([], lltype.Signed)
     dont_keepalive_stuff = False # for tests
+    with_threads = False
 
     def __init__(self, rtyper, stats, opts=None, translate_support_code=False,
                  gcdescr=None):
@@ -38,6 +39,7 @@
                 if not oprofile.OPROFILE_AVAILABLE:
                     log.WARNING('oprofile support was explicitly enabled, but 
oprofile headers seem not to be available')
                 profile_agent = oprofile.OProfileAgent()
+            self.with_threads = config.translation.thread
 
         self.profile_agent = profile_agent
 
diff --git a/pypy/jit/backend/x86/test/test_zrpy_gc.py 
b/pypy/jit/backend/x86/test/test_zrpy_gc.py
--- a/pypy/jit/backend/x86/test/test_zrpy_gc.py
+++ b/pypy/jit/backend/x86/test/test_zrpy_gc.py
@@ -674,7 +674,8 @@
         #
         res = compile_and_run(get_entry(get_g(main)), DEFL_GC,
                               gcrootfinder=self.gcrootfinder, jit=True,
-                              enable_opts=ALL_OPTS_NAMES)
+                              enable_opts=ALL_OPTS_NAMES,
+                              thread=True)
         assert int(res) == 20
 
 class TestOtherShadowStack(OtherFrameworkGCTests):
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,6 +491,7 @@
     # ^^^ 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,6 +973,12 @@
         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'):
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to