Author: Armin Rigo <[email protected]>
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
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit