[pypy-commit] pypy shadowstack-perf-2: tests, code

arigo pypy.commits at gmail.com
Wed May 11 10:47:00 EDT 2016


Author: Armin Rigo <arigo at tunes.org>
Branch: shadowstack-perf-2
Changeset: r84376:142d9abed9dd
Date: 2016-05-11 16:47 +0200
http://bitbucket.org/pypy/pypy/changeset/142d9abed9dd/

Log:	tests, code

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
@@ -1,28 +1,68 @@
+from rpython.flowspace.model import mkentrymap, Variable
+
+
+def is_trivial_rewrite(op):
+    return op.opname in ('same_as', 'cast_pointer', 'cast_opaque_ptr')
+
+
+def find_precessors(graph, pending_pred):
+    """Return the set of variables whose content can end up inside one
+    of the 'pending_pred', which is a list of (block, var) tuples.
+    """
+    entrymap = mkentrymap(graph)
+    pred = set([v for block, v in pending_pred])
+
+    def add(block, v):
+        if isinstance(v, Variable):
+            if v not in pred:
+                pending_pred.append((block, v))
+                pred.add(v)
+
+    while pending_pred:
+        block, v = pending_pred.pop()
+        if v in block.inputargs:
+            var_index = block.inputargs.index(v)
+            for link in entrymap[block]:
+                prevblock = link.prevblock
+                if prevblock is not None:
+                    add(prevblock, link.args[var_index])
+        else:
+            for op in block.operations:
+                if op.result is v:
+                    if is_trivial_rewrite(op):
+                        add(block, op.args[0])
+                    break
+    return pred
 
 
 def find_interesting_variables(graph):
     # Decide which variables are "interesting" or not.  Interesting
     # variables contain at least the ones that appear in gc_push_roots
     # and gc_pop_roots.
-    pending = []
+    pending_pred = []
+    pending_succ = []
     interesting_vars = set()
     for block in graph.iterblocks():
         for op in block.operations:
             if op.opname == 'gc_push_roots':
                 for v in op.args:
                     interesting_vars.add(v)
-                    pending.append((block, v))
+                    pending_pred.append((block, v))
             elif op.opname == 'gc_pop_roots':
                 for v in op.args:
                     assert v in interesting_vars   # must be pushed just above
-    if not interesting_vars:
-        return
+                    pending_succ.append((block, v))
 
     # If there is a path from a gc_pop_roots(v) to a subsequent
     # gc_push_roots(w) where w contains the same value as v along that
     # path, then we consider all intermediate blocks along that path
     # which contain a copy of the same value, and add these variables
-    # as "interesting", too.
+    # as "interesting", too.  Formally, a variable in a block is
+    # "interesting" if it is both a "predecessor" and a "successor",
+    # where predecessors are variables which (sometimes) end in a
+    # gc_push_roots, and successors are variables which (sometimes)
+    # come from a gc_pop_roots.
+
 
     #....
     return interesting_vars
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
@@ -29,15 +29,11 @@
     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 []
-        hop.genop("gc_push_roots", livevars)
+        hop.genop("gc_push_roots", livevars)   # even if len(livevars) == 0
         return livevars
 
     def pop_roots(self, hop, livevars):
-        if not livevars:
-            return
-        hop.genop("gc_pop_roots", livevars)
+        hop.genop("gc_pop_roots", livevars)   # even if len(livevars) == 0
 
 
 class ShadowStackRootWalker(BaseRootWalker):
diff --git a/rpython/memory/gctransform/test/test_shadowcolor.py b/rpython/memory/gctransform/test/test_shadowcolor.py
--- a/rpython/memory/gctransform/test/test_shadowcolor.py
+++ b/rpython/memory/gctransform/test/test_shadowcolor.py
@@ -2,7 +2,7 @@
 from rpython.rtyper.lltypesystem.lloperation import llop
 from rpython.rtyper.test.test_llinterp import gengraph
 from rpython.conftest import option
-from rpython.memory.gctransform.shadowcolor import find_interesting_variables
+from rpython.memory.gctransform.shadowcolor import *
 
 
 def make_graph(f, argtypes):
@@ -19,6 +19,53 @@
     return result
 
 
+def test_find_predecessors_1():
+    def f(a, b):
+        c = a + b
+        return c
+    graph = make_graph(f, [int, int])
+    pred = find_precessors(graph, [(graph.returnblock, graph.getreturnvar())])
+    assert summary(pred) == {'c': 1, 'v': 1}
+
+def test_find_predecessors_2():
+    def f(a, b):
+        c = a + b
+        while a > 0:
+            a -= 2
+        return c
+    graph = make_graph(f, [int, int])
+    pred = find_precessors(graph, [(graph.returnblock, graph.getreturnvar())])
+    assert summary(pred) == {'c': 3, 'v': 1}
+
+def test_find_predecessors_3():
+    def f(a, b):
+        while b > 100:
+            b -= 2
+        if b > 10:
+            c = a + b      # 'c' created in this block
+        else:
+            c = a - b      # 'c' created in this block
+        return c           # 'v' is the return var
+    graph = make_graph(f, [int, int])
+    pred = find_precessors(graph, [(graph.returnblock, graph.getreturnvar())])
+    assert summary(pred) == {'c': 2, 'v': 1}
+
+def test_find_predecessors_4():
+    def f(a, b):           # 'a' in the input block
+        while b > 100:     # 'a' in the loop header block
+            b -= 2         # 'a' in the loop body block
+        if b > 10:         # 'a' in the condition block
+            while b > 5:   # nothing
+                b -= 2     # nothing
+            c = a + b      # 'c' created in this block
+        else:
+            c = a
+        return c           # 'v' is the return var
+    graph = make_graph(f, [int, int])
+    pred = find_precessors(graph, [(graph.returnblock, graph.getreturnvar())])
+    assert summary(pred) == {'a': 4, 'c': 1, 'v': 1}
+
+
 def test_interesting_vars_0():
     def f(a, b):
         pass


More information about the pypy-commit mailing list