Author: Armin Rigo <ar...@tunes.org>
Branch: shadowstack-perf-2
Changeset: r84467:756c71cb1008
Date: 2016-05-15 16:30 +0200
http://bitbucket.org/pypy/pypy/changeset/756c71cb1008/

Log:    Write the C backend code for the new shadowstack operations.

diff --git a/rpython/memory/gctransform/shadowcolor.py 
b/rpython/memory/gctransform/shadowcolor.py
--- a/rpython/memory/gctransform/shadowcolor.py
+++ b/rpython/memory/gctransform/shadowcolor.py
@@ -123,14 +123,12 @@
     return SpaceOperation('gc_restore_root', [c_index, var],
                           varoftype(lltype.Void))
 
-c_NULL = Constant(lltype.nullptr(llmemory.GCREF.TO), llmemory.GCREF)
-
 def make_bitmask(filled):
     n = filled.count(False)
     if n == 0:
         return (None, None)
     if n == 1:
-        return (filled.index(False), c_NULL)
+        return (filled.index(False), 0)
     bitmask = 0
     last_index = 0
     for i in range(len(filled)):
@@ -139,7 +137,7 @@
             last_index = i
             bitmask |= 1
     assert bitmask & 1
-    return (last_index, Constant(bitmask, lltype.Signed))
+    return (last_index, bitmask)
 
 
 def expand_one_push_roots(regalloc, args):
@@ -152,11 +150,12 @@
             assert not filled[index]
             filled[index] = True
             yield _gc_save_root(index, v)
-        bitmask_index, bitmask_c = make_bitmask(filled)
+        bitmask_index, bitmask = make_bitmask(filled)
         if bitmask_index is not None:
             # xxx we might in some cases avoid this gc_save_root
             # entirely, if we know we're after another gc_push/gc_pop
             # that wrote exactly the same mask at the same index
+            bitmask_c = Constant(bitmask, lltype.Signed)
             yield _gc_save_root(bitmask_index, bitmask_c)
 
 def expand_one_pop_roots(regalloc, args):
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
@@ -59,10 +59,22 @@
         def walk_stack_root(callback, start, end):
             gc = self.gc
             addr = end
+            skip = 0
             while addr != start:
                 addr -= sizeofaddr
-                if gc.points_to_valid_gc_object(addr):
-                    callback(gc, addr)
+                #XXX reintroduce support for tagged values?
+                #if gc.points_to_valid_gc_object(addr):
+                #    callback(gc, addr)
+
+                if skip & 1 == 0:
+                    content = addr.address[0]
+                    if content:
+                        n = llmemory.cast_adr_to_int(content)
+                        if n & 1 == 0:
+                            callback(gc, addr)  # non-0, non-odd: a regular ptr
+                        else:
+                            skip = n            # odd number: a skip bitmask
+                skip >>= 1
         self.rootstackhook = walk_stack_root
 
         self.shadow_stack_pool = ShadowStackPool(gcdata)
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
@@ -33,6 +33,7 @@
     Collects information about a function which we have to generate
     from a flow graph.
     """
+    pre_return_code = None
 
     def __init__(self, graph, db, exception_policy, functionname):
         self.graph = graph
@@ -173,6 +174,12 @@
 
     def cfunction_body(self):
         graph = self.graph
+        if (len(graph.startblock.operations) >= 1 and
+            graph.startblock.operations[0].opname == 'gc_enter_roots_frame'):
+            for line in self.gcpolicy.enter_roots_frame(self,
+                                        graph.startblock.operations[0]):
+                yield line
+
         yield 'goto block0;'    # to avoid a warning "this label is not used"
 
         # generate the body of each block
@@ -193,6 +200,8 @@
                 retval = self.expr(block.inputargs[0])
                 if self.exception_policy != "exc_helper":
                     yield 'RPY_DEBUG_RETURN();'
+                if self.pre_return_code:
+                    yield self.pre_return_code
                 yield 'return %s;' % retval
                 continue
             elif block.exitswitch is None:
diff --git a/rpython/translator/c/gc.py b/rpython/translator/c/gc.py
--- a/rpython/translator/c/gc.py
+++ b/rpython/translator/c/gc.py
@@ -397,6 +397,39 @@
         from rpython.memory.gctransform import shadowstack
         return shadowstack.ShadowStackFrameworkGCTransformer(translator)
 
+    def enter_roots_frame(self, funcgen, op):
+        numcolors = op.args[1].value
+        c_gcdata = op.args[0]
+        # XXX hard-code the field name here
+        gcpol_ss = '%s->gcd_inst_root_stack_top' % funcgen.expr(c_gcdata)
+        #
+        yield ('typedef struct { void %s; } pypy_ss_t;'
+                   % ', '.join(['*s%d' % i for i in range(numcolors)]))
+        yield 'pypy_ss_t *ss = (pypy_ss_t *)%s;' % gcpol_ss
+        funcgen.gcpol_ss = gcpol_ss
+        funcgen.pre_return_code = '%s = (void *)ss;' % gcpol_ss
+
+    def OP_GC_ENTER_ROOTS_FRAME(self, funcgen, op):
+        if op is not funcgen.graph.startblock.operations[0]:
+            raise Exception("gc_enter_roots_frame as a non-initial 
instruction")
+        return '%s = (void *)(ss+1);' % funcgen.gcpol_ss
+
+    def OP_GC_SAVE_ROOT(self, funcgen, op):
+        num = op.args[0].value
+        exprvalue = funcgen.expr(op.args[1])
+        return 'ss->s%d = (void *)%s;\t/* gc_save_root */' % (num, exprvalue)
+
+    def OP_GC_RESTORE_ROOT(self, funcgen, op):
+        num = op.args[0].value
+        exprvalue = funcgen.expr(op.args[1])
+        typename = funcgen.db.gettype(op.args[1].concretetype)
+        result = '%s = (%s)ss->s%d;' % (exprvalue, cdecl(typename, ''), num)
+        if isinstance(op.args[1], Constant):
+            return '/* %s\t* gc_restore_root */' % result
+        else:
+            return '%s\t/* gc_restore_root */' % result
+
+
 class AsmGcRootFrameworkGcPolicy(BasicFrameworkGcPolicy):
 
     def gettransformer(self, translator):
diff --git a/rpython/translator/c/node.py b/rpython/translator/c/node.py
--- a/rpython/translator/c/node.py
+++ b/rpython/translator/c/node.py
@@ -845,8 +845,7 @@
                 self.name, self.db.standalone, is_exported=is_exported))
 
     def graphs_to_patch(self):
-        for i in self.funcgen.graphs_to_patch():
-            yield i
+        return self.funcgen.graphs_to_patch()
 
     def implementation(self):
         funcgen = self.funcgen
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to