Author: Armin Rigo <[email protected]>
Branch: r15-for-shadowstack
Changeset: r65976:7262c0519909
Date: 2013-08-06 16:47 +0200
http://bitbucket.org/pypy/pypy/changeset/7262c0519909/

Log:    in-progress, targetgcbench works

diff --git a/rpython/memory/gctransform/framework.py 
b/rpython/memory/gctransform/framework.py
--- a/rpython/memory/gctransform/framework.py
+++ b/rpython/memory/gctransform/framework.py
@@ -784,6 +784,7 @@
         self._gc_adr_of_gc_attr(hop, 'nursery_top')
 
     def _gc_adr_of_gcdata_attr(self, hop, attrname):
+        xxxxxxxxxxxxxx
         op = hop.spaceop
         ofs = llmemory.offsetof(self.c_const_gcdata.concretetype.TO,
                                 'inst_' + attrname)
diff --git a/rpython/memory/gctransform/shadowstack.py 
b/rpython/memory/gctransform/shadowstack.py
--- a/rpython/memory/gctransform/shadowstack.py
+++ b/rpython/memory/gctransform/shadowstack.py
@@ -4,7 +4,8 @@
 from rpython.rlib import rgc
 from rpython.rtyper import rmodel
 from rpython.rtyper.annlowlevel import llhelper
-from rpython.rtyper.lltypesystem import lltype, llmemory
+from rpython.rtyper.lltypesystem import lltype, llmemory, rffi
+from rpython.rtyper.lltypesystem.lloperation import llop
 from rpython.memory.gctransform.framework import (
      BaseFrameworkGCTransformer, BaseRootWalker, sizeofaddr)
 from rpython.rtyper.rbuiltin import gen_cast
@@ -12,14 +13,7 @@
 
 class ShadowStackFrameworkGCTransformer(BaseFrameworkGCTransformer):
     def annotate_walker_functions(self, getfn):
-        self.incr_stack_ptr = getfn(self.root_walker.incr_stack,
-                                   [annmodel.SomeInteger()],
-                                   annmodel.SomeAddress(),
-                                   inline = True)
-        self.decr_stack_ptr = getfn(self.root_walker.decr_stack,
-                                   [annmodel.SomeInteger()],
-                                   annmodel.SomeAddress(),
-                                   inline = True)
+        pass
 
     def build_root_walker(self):
         return ShadowStackRootWalker(self)
@@ -27,30 +21,13 @@
     def push_roots(self, hop, keep_current_args=False):
         livevars = self.get_livevars_for_roots(hop, keep_current_args)
         self.num_pushs += len(livevars)
-        if not livevars:
-            return []
-        c_len = rmodel.inputconst(lltype.Signed, len(livevars) )
-        base_addr = hop.genop("direct_call", [self.incr_stack_ptr, c_len ],
-                              resulttype=llmemory.Address)
-        for k,var in enumerate(livevars):
-            c_k = rmodel.inputconst(lltype.Signed, k * sizeofaddr)
-            v_adr = gen_cast(hop.llops, llmemory.Address, var)
-            hop.genop("raw_store", [base_addr, c_k, v_adr])
+        hop.genop("shadowstack_push", list(livevars))    # may be 0
         return livevars
 
     def pop_roots(self, hop, livevars):
         if not livevars:
             return
-        c_len = rmodel.inputconst(lltype.Signed, len(livevars) )
-        base_addr = hop.genop("direct_call", [self.decr_stack_ptr, c_len ],
-                              resulttype=llmemory.Address)
-        if self.gcdata.gc.moving_gc:
-            # for moving collectors, reload the roots into the local variables
-            for k,var in enumerate(livevars):
-                c_k = rmodel.inputconst(lltype.Signed, k * sizeofaddr)
-                v_newaddr = hop.genop("raw_load", [base_addr, c_k],
-                                      resulttype=llmemory.Address)
-                hop.genop("gc_reload_possibly_moved", [v_newaddr, var])
+        hop.genop("shadowstack_pop", list(livevars))
 
 
 class ShadowStackRootWalker(BaseRootWalker):
@@ -59,53 +36,21 @@
         # NB. 'self' is frozen, but we can use self.gcdata to store state
         gcdata = self.gcdata
 
-        def incr_stack(n):
-            top = gcdata.root_stack_top
-            gcdata.root_stack_top = top + n*sizeofaddr
-            return top
-        self.incr_stack = incr_stack
-
-        def decr_stack(n):
-            top = gcdata.root_stack_top - n*sizeofaddr
-            gcdata.root_stack_top = top
-            return top
-        self.decr_stack = decr_stack
-
-        root_iterator = get_root_iterator(gctransformer)
-        def walk_stack_root(callback, start, end):
-            root_iterator.setcontext(NonConstant(llmemory.NULL))
-            gc = self.gc
-            addr = end
-            while True:
-                addr = root_iterator.nextleft(gc, start, addr)
-                if addr == llmemory.NULL:
-                    return
-                callback(gc, addr)
-        self.rootstackhook = walk_stack_root
-
-        self.shadow_stack_pool = ShadowStackPool(gcdata)
-        rsd = gctransformer.root_stack_depth
-        if rsd is not None:
-            self.shadow_stack_pool.root_stack_depth = rsd
-
-    def push_stack(self, addr):
-        top = self.incr_stack(1)
-        top.address[0] = addr
-
-    def pop_stack(self):
-        top = self.decr_stack(1)
-        return top.address[0]
-
-    def setup_root_walker(self):
-        self.shadow_stack_pool.initial_setup()
-        BaseRootWalker.setup_root_walker(self)
-
     def walk_stack_roots(self, collect_stack_root):
-        gcdata = self.gcdata
-        self.rootstackhook(collect_stack_root,
-                           gcdata.root_stack_base, gcdata.root_stack_top)
+        WORD = llmemory.sizeof(llmemory.Address)
+        r15 = llop.shadowstack_r15(lltype.Signed)
+        gc = self.gc
+        while r15 != -1:
+            n = (r15 & 7) + 1
+            r15 &= ~7
+            while n > 0:
+                addr = rffi.cast(llmemory.Address, r15 + n * WORD)
+                collect_stack_root(gc, addr)
+                n -= 1
+            r15 = rffi.cast(llmemory.Address, r15).signed[0]
 
     def need_thread_support(self, gctransformer, getfn):
+        xxxxxxxxx
         from rpython.rlib import rthread    # xxx fish
         gcdata = self.gcdata
         # the interfacing between the threads and the GC is done via
@@ -216,6 +161,7 @@
                                            minimal_transform=False)
 
     def need_stacklet_support(self, gctransformer, getfn):
+        xxxxxxxxxxxxx
         shadow_stack_pool = self.shadow_stack_pool
         SHADOWSTACKREF = get_shadowstackref(self, gctransformer)
 
@@ -264,156 +210,3 @@
                                                   inline=True)
 
 # ____________________________________________________________
-
-class ShadowStackPool(object):
-    """Manages a pool of shadowstacks.  The MAX most recently used
-    shadowstacks are fully allocated and can be directly jumped into.
-    The rest are stored in a more virtual-memory-friendly way, i.e.
-    with just the right amount malloced.  Before they can run, they
-    must be copied into a full shadowstack.  XXX NOT IMPLEMENTED SO FAR!
-    """
-    _alloc_flavor_ = "raw"
-    root_stack_depth = 163840
-
-    #MAX = 20  not implemented yet
-
-    def __init__(self, gcdata):
-        self.unused_full_stack = llmemory.NULL
-        self.gcdata = gcdata
-
-    def initial_setup(self):
-        self._prepare_unused_stack()
-        self.start_fresh_new_state()
-
-    def allocate(self, SHADOWSTACKREF):
-        """Allocate an empty SHADOWSTACKREF object."""
-        return lltype.malloc(SHADOWSTACKREF, zero=True)
-
-    def save_current_state_away(self, shadowstackref, ncontext):
-        """Save the current state away into 'shadowstackref'.
-        This either works, or raise MemoryError and nothing is done.
-        To do a switch, first call save_current_state_away() or
-        forget_current_state(), and then call restore_state_from()
-        or start_fresh_new_state().
-        """
-        self._prepare_unused_stack()
-        shadowstackref.base = self.gcdata.root_stack_base
-        shadowstackref.top  = self.gcdata.root_stack_top
-        shadowstackref.context = ncontext
-        ll_assert(shadowstackref.base <= shadowstackref.top,
-                  "save_current_state_away: broken shadowstack")
-        #shadowstackref.fullstack = True
-        #
-        # cannot use llop.gc_assume_young_pointers() here, because
-        # we are in a minimally-transformed GC helper :-/
-        gc = self.gcdata.gc
-        if hasattr(gc.__class__, 'assume_young_pointers'):
-            shadowstackadr = llmemory.cast_ptr_to_adr(shadowstackref)
-            gc.assume_young_pointers(shadowstackadr)
-        #
-        self.gcdata.root_stack_top = llmemory.NULL  # to detect missing restore
-
-    def forget_current_state(self):
-        ll_assert(self.gcdata.root_stack_base == self.gcdata.root_stack_top,
-                  "forget_current_state: shadowstack not empty!")
-        if self.unused_full_stack:
-            llmemory.raw_free(self.unused_full_stack)
-        self.unused_full_stack = self.gcdata.root_stack_base
-        self.gcdata.root_stack_top = llmemory.NULL  # to detect missing restore
-
-    def restore_state_from(self, shadowstackref):
-        ll_assert(bool(shadowstackref.base), "empty shadowstackref!")
-        ll_assert(shadowstackref.base <= shadowstackref.top,
-                  "restore_state_from: broken shadowstack")
-        self.gcdata.root_stack_base = shadowstackref.base
-        self.gcdata.root_stack_top  = shadowstackref.top
-        self._cleanup(shadowstackref)
-
-    def start_fresh_new_state(self):
-        self.gcdata.root_stack_base = self.unused_full_stack
-        self.gcdata.root_stack_top  = self.unused_full_stack
-        self.unused_full_stack = llmemory.NULL
-
-    def _cleanup(self, shadowstackref):
-        shadowstackref.base = llmemory.NULL
-        shadowstackref.top = llmemory.NULL
-        shadowstackref.context = llmemory.NULL
-
-    def _prepare_unused_stack(self):
-        if self.unused_full_stack == llmemory.NULL:
-            root_stack_size = sizeofaddr * self.root_stack_depth
-            self.unused_full_stack = llmemory.raw_malloc(root_stack_size)
-            if self.unused_full_stack == llmemory.NULL:
-                raise MemoryError
-
-
-def get_root_iterator(gctransformer):
-    if hasattr(gctransformer, '_root_iterator'):
-        return gctransformer._root_iterator     # if already built
-    class RootIterator(object):
-        def _freeze_(self):
-            return True
-        def setcontext(self, context):
-            pass
-        def nextleft(self, gc, start, addr):
-            while addr != start:
-                addr -= sizeofaddr
-                if gc.points_to_valid_gc_object(addr):
-                    return addr
-            return llmemory.NULL
-    result = RootIterator()
-    gctransformer._root_iterator = result
-    return result
-
-
-def get_shadowstackref(root_walker, gctransformer):
-    if hasattr(gctransformer, '_SHADOWSTACKREF'):
-        return gctransformer._SHADOWSTACKREF
-
-    SHADOWSTACKREFPTR = lltype.Ptr(lltype.GcForwardReference())
-    SHADOWSTACKREF = lltype.GcStruct('ShadowStackRef',
-                                     ('base', llmemory.Address),
-                                     ('top', llmemory.Address),
-                                     ('context', llmemory.Address),
-                                     #('fullstack', lltype.Bool),
-                                     rtti=True)
-    SHADOWSTACKREFPTR.TO.become(SHADOWSTACKREF)
-
-    gc = gctransformer.gcdata.gc
-    root_iterator = get_root_iterator(gctransformer)
-
-    def customtrace(obj, prev):
-        obj = llmemory.cast_adr_to_ptr(obj, SHADOWSTACKREFPTR)
-        if not prev:
-            root_iterator.setcontext(obj.context)
-            prev = obj.top
-        return root_iterator.nextleft(gc, obj.base, prev)
-
-    CUSTOMTRACEFUNC = lltype.FuncType([llmemory.Address, llmemory.Address],
-                                      llmemory.Address)
-    customtraceptr = llhelper(lltype.Ptr(CUSTOMTRACEFUNC), customtrace)
-
-    def shadowstack_destructor(shadowstackref):
-        if root_walker.stacklet_support:
-            from rpython.rlib import _rffi_stacklet as _c
-            h = shadowstackref.context
-            h = llmemory.cast_adr_to_ptr(h, _c.handle)
-            shadowstackref.context = llmemory.NULL
-        #
-        base = shadowstackref.base
-        shadowstackref.base    = llmemory.NULL
-        shadowstackref.top     = llmemory.NULL
-        llmemory.raw_free(base)
-        #
-        if root_walker.stacklet_support:
-            if h:
-                _c.destroy(h)
-
-    destrptr = gctransformer.annotate_helper(shadowstack_destructor,
-                                             [SHADOWSTACKREFPTR], lltype.Void)
-
-    lltype.attachRuntimeTypeInfo(SHADOWSTACKREF, customtraceptr=customtraceptr,
-                                 destrptr=destrptr)
-
-    gctransformer._SHADOWSTACKREF = SHADOWSTACKREF
-    return SHADOWSTACKREF
diff --git a/rpython/rtyper/lltypesystem/lloperation.py 
b/rpython/rtyper/lltypesystem/lloperation.py
--- a/rpython/rtyper/lltypesystem/lloperation.py
+++ b/rpython/rtyper/lltypesystem/lloperation.py
@@ -561,6 +561,10 @@
     'debug_print_traceback':   LLOp(),
     'debug_nonnull_pointer':   LLOp(canrun=True),
 
+    'shadowstack_push':     LLOp(),
+    'shadowstack_pop':      LLOp(),
+    'shadowstack_r15':      LLOp(),
+
     # __________ instrumentation _________
     'instrument_count':     LLOp(),
 }
diff --git a/rpython/translator/c/funcgen.py b/rpython/translator/c/funcgen.py
--- a/rpython/translator/c/funcgen.py
+++ b/rpython/translator/c/funcgen.py
@@ -204,6 +204,8 @@
 
     def cfunction_body(self):
         graph = self.graph
+        yield 'char *shadowstack[9];  /* xxx reduce */'
+        yield 'shadowstack[0] = pypy_r15;'
         yield 'goto block0;'    # to avoid a warning "this label is not used"
 
         # generate the body of each block
@@ -899,4 +901,34 @@
         else:
             return None    # use the default
 
+    def OP_SHADOWSTACK_PUSH(self, op):
+        numvars = len(op.args)
+        if numvars == 0:
+            return 'pypy_r15 = shadowstack[0];'
+        else:
+            assert numvars <= 8
+            exprs = []
+            for i in range(numvars):
+                exprs.append('shadowstack[%d] = (char *)%s;' % (
+                    i + 1, self.expr(op.args[i])))
+            exprs.append('pypy_r15 = ((char *)shadowstack) + %d;' % (
+                numvars - 1,))
+            return '\n'.join(exprs)
+
+    def OP_SHADOWSTACK_POP(self, op):
+        numvars = len(op.args)
+        assert 1 <= numvars <= 8
+        exprs = []
+        for i in range(numvars-1, -1, -1):
+            v = op.args[i]
+            exprs.append('%s = (%s)shadowstack[%d];' % (
+                self.expr(v), cdecl(self.lltypename(v), ''), i + 1))
+        return '\n'.join(exprs)
+
+    def OP_SHADOWSTACK_R15(self, op):
+        v = op.result
+        return '%s = (%s)pypy_r15;' % (self.expr(v),
+                                       cdecl(self.lltypename(v), ''))
+
+
 assert not USESLOTS or '__dict__' not in dir(FunctionCodeGenerator)
diff --git a/rpython/translator/c/src/entrypoint.c 
b/rpython/translator/c/src/entrypoint.c
--- a/rpython/translator/c/src/entrypoint.c
+++ b/rpython/translator/c/src/entrypoint.c
@@ -30,14 +30,18 @@
     char *errmsg;
     int i, exitcode;
     RPyListOfString *list;
+    char *saved_r15;
 
 #ifdef PYPY_USE_ASMGCC
     
pypy_g_rpython_rtyper_lltypesystem_rffi_StackCounter.sc_inst_stacks_counter++;
 #endif
-    pypy_asm_stack_bottom();
+    saved_r15 = pypy_r15;
+    //pypy_asm_stack_bottom();
 #ifdef PYPY_X86_CHECK_SSE2_DEFINED
+    pypy_r15 = (char *)-1;
     pypy_x86_check_sse2();
 #endif
+    pypy_r15 = (char *)-1;
     instrument_setup();
 
 #ifndef MS_WINDOWS
@@ -49,28 +53,37 @@
     }
 #endif
 
+    pypy_r15 = (char *)-1;
     errmsg = RPython_StartupCode();
     if (errmsg) goto error;
 
+    pypy_r15 = (char *)-1;
     list = _RPyListOfString_New(argc);
     if (RPyExceptionOccurred()) goto memory_out;
     for (i=0; i<argc; i++) {
+        pypy_r15 = (char *)-1;
         RPyString *s = RPyString_FromString(argv[i]);
         if (RPyExceptionOccurred()) goto memory_out;
+        pypy_r15 = (char *)-1;
         _RPyListOfString_SetItem(list, i, s);
     }
 
+    pypy_r15 = (char *)-1;
     exitcode = STANDALONE_ENTRY_POINT(list);
 
+    pypy_r15 = (char *)-1;
     pypy_debug_alloc_results();
 
+    pypy_r15 = (char *)-1;
     if (RPyExceptionOccurred()) {
         /* print the RPython traceback */
         pypy_debug_catch_fatal_exception();
     }
 
+    pypy_r15 = (char *)-1;
     pypy_malloc_counters_results();
 
+    pypy_r15 = saved_r15;
     return exitcode;
 
  memory_out:
@@ -78,7 +91,7 @@
  error:
     fprintf(stderr, "Fatal error during initialization: %s\n", errmsg);
     abort();
-    return 1;
+    return 1;   /* not actually reachable */
 }
 
 int PYPY_MAIN_FUNCTION(int argc, char *argv[])
diff --git a/rpython/translator/c/src/g_prerequisite.h 
b/rpython/translator/c/src/g_prerequisite.h
--- a/rpython/translator/c/src/g_prerequisite.h
+++ b/rpython/translator/c/src/g_prerequisite.h
@@ -26,3 +26,6 @@
 
 
 #include "src/align.h"
+
+
+register char *pypy_r15 asm("r15");
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to