def insert_stackcheck(ann): from pypy.tool.algo.graphlib import Edge, make_edge_dict, break_cycles edges = [] graphs_to_patch = {} for callposition, (caller, callee) in ann.translator.callgraph.items(): if getattr(getattr(callee, 'func', None), 'insert_stack_check_here', False): graphs_to_patch[callee] = True continue edge = Edge(caller, callee) edge.callposition = callposition edges.append(edge) for graph in graphs_to_patch: v = Variable() ann.setbinding(v, annmodel.SomeImpossibleValue()) unwind_op = SpaceOperation('simple_call', [Constant(stack_check)], v) graph.startblock.operations.insert(0, unwind_op) edgedict = make_edge_dict(edges) for edge in break_cycles(edgedict, edgedict): caller = edge.source _, _, call_tag = edge.callposition if call_tag: caller_block, _ = call_tag else: ann.warning("cycle detected but no information on where to insert " "stack_check()") continue # caller block found, insert stack_check() v = Variable() # push annotation on v ann.setbinding(v, annmodel.SomeImpossibleValue()) unwind_op = SpaceOperation('simple_call', [Constant(stack_check)], v) caller_block.operations.insert(0, unwind_op)
def insert_ll_stackcheck(translator): from pypy.translator.backendopt.support import find_calls_from from pypy.rlib.rstack import stack_check from pypy.tool.algo.graphlib import Edge, make_edge_dict, break_cycles_v rtyper = translator.rtyper graph = rtyper.annotate_helper(stack_check, []) rtyper.specialize_more_blocks() stack_check_ptr = rtyper.getcallable(graph) stack_check_ptr_const = Constant(stack_check_ptr, lltype.typeOf(stack_check_ptr)) edges = set() insert_in = set() for caller in translator.graphs: for block, callee in find_calls_from(translator, caller): if getattr(getattr(callee, 'func', None), 'insert_stack_check_here', False): insert_in.add(callee.startblock) continue if block is not caller.startblock: edges.add((caller.startblock, block)) edges.add((block, callee.startblock)) edgelist = [Edge(block1, block2) for (block1, block2) in edges] edgedict = make_edge_dict(edgelist) for block in break_cycles_v(edgedict, edgedict): insert_in.add(block) for block in insert_in: v = Variable() v.concretetype = lltype.Void unwind_op = SpaceOperation('direct_call', [stack_check_ptr_const], v) block.operations.insert(0, unwind_op) return len(insert_in)
def insert_ll_stackcheck(translator): from pypy.translator.backendopt.support import find_calls_from from pypy.rlib.rstack import stack_check from pypy.tool.algo.graphlib import Edge, make_edge_dict, break_cycles rtyper = translator.rtyper graph = rtyper.annotate_helper(stack_check, []) rtyper.specialize_more_blocks() stack_check_ptr = rtyper.getcallable(graph) stack_check_ptr_const = Constant(stack_check_ptr, lltype.typeOf(stack_check_ptr)) edges = [] graphs_to_patch = {} insert_in = {} for caller in translator.graphs: for block, callee in find_calls_from(translator, caller): if getattr(getattr(callee, 'func', None), 'insert_stack_check_here', False): insert_in[callee.startblock] = True continue edge = Edge(caller, callee) edge.block = block edges.append(edge) edgedict = make_edge_dict(edges) for edge in break_cycles(edgedict, edgedict): block = edge.block insert_in[block] = True for block in insert_in: v = Variable() v.concretetype = lltype.Void unwind_op = SpaceOperation('direct_call', [stack_check_ptr_const], v) block.operations.insert(0, unwind_op) return len(insert_in)