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