[pypy-commit] pypy shadowstack-perf-2: Double-check using a very different algorithm

arigo pypy.commits at gmail.com
Mon May 16 09:27:08 EDT 2016


Author: Armin Rigo <arigo at tunes.org>
Branch: shadowstack-perf-2
Changeset: r84480:6d8934908ce2
Date: 2016-05-15 19:05 +0200
http://bitbucket.org/pypy/pypy/changeset/6d8934908ce2/

Log:	Double-check using a very different algorithm

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
@@ -438,6 +438,81 @@
                         # new blocks made by insert_empty_block() earlier
 
 
+class PostProcessCheckError(Exception):
+    pass
+
+def postprocess_double_check(graph):
+    # Debugging only: double-check that the placement is correct.
+    # Assumes that every gc_restore_root() indicates that the variable
+    # must be saved at the given position in the shadowstack frame (in
+    # practice it may have moved because of the GC, but in theory it
+    # is still the "same" object).  So we build the set of all known
+    # valid-in-all-paths saved locations, and check that.
+
+    saved = {}  # {var-from-inputargs: location} where location is:
+                #    <unset>: we haven't seen this variable so far
+                #    set-of-indexes: says where the variable is always
+                #                    saved at the start of this block
+                #    empty-set: same as above, so: "saved nowhere"
+
+    for v in graph.startblock.inputargs:
+        saved[v] = frozenset()    # function arguments are not saved anywhere
+
+    pending = set([graph.startblock])
+    while pending:
+        block = pending.pop()
+        locsaved = {}
+        for v in block.inputargs:
+            locsaved[v] = saved[v]
+        for op in block.operations:
+            if op.opname == 'gc_restore_root':
+                if isinstance(op.args[1], Constant):
+                    continue
+                num = op.args[0].value
+                if num not in locsaved[op.args[1]]:
+                    raise PostProcessCheckError(graph, block, op, num, locsaved)
+            elif op.opname == 'gc_save_root':
+                num = op.args[0].value
+                v = op.args[1]
+                if isinstance(v, Variable):
+                    locsaved[v] = locsaved[v].union([num])
+                else:
+                    if v.concretetype != lltype.Signed:
+                        locsaved[v] = locsaved.get(v, frozenset()).union([num])
+                        continue
+                    bitmask = v.value
+                    if bitmask == 0:
+                        bitmask = 1
+                    assert bitmask & 1
+                    assert bitmask < (2<<num)
+                    nummask = [i for i in range(num+1)
+                                 if bitmask & (1<<(num-i))]
+                    assert nummask[-1] == num
+                    for v in locsaved:
+                        locsaved[v] = locsaved[v].difference(nummask)
+            elif is_trivial_rewrite(op):
+                locsaved[op.result] = locsaved[op.args[0]]
+            else:
+                locsaved[op.result] = frozenset()
+        for link in block.exits:
+            changed = False
+            for i, v in enumerate(link.args):
+                try:
+                    loc = locsaved[v]
+                except KeyError:
+                    assert isinstance(v, Constant)
+                    loc = frozenset()
+                w = link.target.inputargs[i]
+                if w in saved:
+                    if loc == saved[w]:
+                        continue      # already up-to-date
+                    loc = loc.intersection(saved[w])
+                saved[w] = loc
+                changed = True
+            if changed:
+                pending.add(link.target)
+
+
 def postprocess_graph(graph, c_gcdata):
     """Collect information about the gc_push_roots and gc_pop_roots
     added in this complete graph, and replace them with real operations.
@@ -448,3 +523,4 @@
     expand_pop_roots(graph, regalloc)
     add_enter_roots_frame(graph, regalloc, c_gcdata)
     checkgraph(graph)
+    postprocess_double_check(graph)
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
@@ -336,6 +336,7 @@
     assert len(graph.startblock.operations) == 1
     assert graph.startblock.operations[0].opname == 'gc_save_root'
     assert graph.startblock.operations[0].args[0].value == 0
+    postprocess_double_check(graph)
 
 def test_move_pushes_earlier_2():
     def g(a):
@@ -363,6 +364,7 @@
         'int_sub': 1,
         'direct_call': 2,
         }
+    postprocess_double_check(graph)
 
 def test_remove_intrablock_push_roots():
     def g(a):
@@ -416,6 +418,7 @@
         'int_sub': 1,
         'direct_call': 2,
         }
+    postprocess_double_check(graph)
 
 def test_move_pushes_earlier_rename_2():
     def g(a):
@@ -445,6 +448,7 @@
         'int_sub': 1,
         'direct_call': 2,
         }
+    postprocess_double_check(graph)
 
 def test_move_pushes_earlier_rename_3():
     def g(a):
@@ -476,6 +480,7 @@
         'int_sub': 2,
         'direct_call': 2,
         }
+    postprocess_double_check(graph)
 
 def test_move_pushes_earlier_rename_4():
     def g(a):
@@ -515,3 +520,4 @@
         'int_sub': 3,
         'direct_call': 2,
         }
+    postprocess_double_check(graph)


More information about the pypy-commit mailing list