[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