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