def create_exception_handling(self, graph): """After an exception in a direct_call (or indirect_call), that is not caught by an explicit except statement, we need to reraise the exception. So after this direct_call we need to test if an exception had occurred. If so, we return from the current graph with a special value (False/-1/-1.0/null). Because of the added exitswitch we need an additional block. """ if hasattr(graph, "exceptiontransformed"): assert self.same_obj(self.exc_data_ptr, graph.exceptiontransformed) return else: self.raise_analyzer.analyze_direct_call(graph) graph.exceptiontransformed = self.exc_data_ptr join_blocks(graph) # collect the blocks before changing them n_need_exc_matching_blocks = 0 n_gen_exc_checks = 0 # entrymap = mkentrymap(graph) if graph.exceptblock in entrymap: for link in entrymap[graph.exceptblock]: self.transform_jump_to_except_block(graph, entrymap, link) # for block in list(graph.iterblocks()): self.replace_fetch_restore_operations(block) need_exc_matching, gen_exc_checks = self.transform_block(graph, block) n_need_exc_matching_blocks += need_exc_matching n_gen_exc_checks += gen_exc_checks cleanup_graph(graph) return n_need_exc_matching_blocks, n_gen_exc_checks
def create_exception_handling(self, graph, always_exc_clear=False): """After an exception in a direct_call (or indirect_call), that is not caught by an explicit except statement, we need to reraise the exception. So after this direct_call we need to test if an exception had occurred. If so, we return from the current graph with a special value (False/-1/-1.0/null). Because of the added exitswitch we need an additional block. """ if hasattr(graph, 'exceptiontransformed'): assert self.same_obj(self.exc_data_ptr, graph.exceptiontransformed) return else: self.raise_analyzer.analyze_direct_call(graph) graph.exceptiontransformed = self.exc_data_ptr self.always_exc_clear = always_exc_clear join_blocks(graph) # collect the blocks before changing them n_need_exc_matching_blocks = 0 n_gen_exc_checks = 0 for block in list(graph.iterblocks()): self.replace_stack_unwind(block) self.replace_fetch_restore_operations(block) need_exc_matching, gen_exc_checks = self.transform_block( graph, block) n_need_exc_matching_blocks += need_exc_matching n_gen_exc_checks += gen_exc_checks self.transform_except_block(graph, graph.exceptblock) cleanup_graph(graph) removenoops.remove_superfluous_keep_alive(graph) return n_need_exc_matching_blocks, n_gen_exc_checks
def test_replace_exitswitch_by_constant_bug(): class X: pass def constant9(): x = X() x.n = 3 x.n = 9 return x.n def fn(): n = constant9() if n == 1: return 5 elif n == 2: return 6 elif n == 3: return 8 elif n == 4: return -123 elif n == 5: return 12973 else: return n t = TranslationContext() a = t.buildannotator() a.build_types(fn, []) rtyper = t.buildrtyper() rtyper.specialize() graph = t.graphs[0] remove_same_as(graph) merge_if_blocks_once(graph) from pypy.translator.backendopt import malloc, inline inline.auto_inlining(t, 20) malloc.remove_mallocs(t, t.graphs) from pypy.translator import simplify simplify.join_blocks(graph)
def create_exception_handling(self, graph): """After an exception in a direct_call (or indirect_call), that is not caught by an explicit except statement, we need to reraise the exception. So after this direct_call we need to test if an exception had occurred. If so, we return from the current graph with a special value (False/-1/-1.0/null). Because of the added exitswitch we need an additional block. """ if hasattr(graph, 'exceptiontransformed'): assert self.same_obj(self.exc_data_ptr, graph.exceptiontransformed) return else: self.raise_analyzer.analyze_direct_call(graph) graph.exceptiontransformed = self.exc_data_ptr join_blocks(graph) # collect the blocks before changing them n_need_exc_matching_blocks = 0 n_gen_exc_checks = 0 # entrymap = mkentrymap(graph) if graph.exceptblock in entrymap: for link in entrymap[graph.exceptblock]: self.transform_jump_to_except_block(graph, entrymap, link) # for block in list(graph.iterblocks()): self.replace_fetch_restore_operations(block) need_exc_matching, gen_exc_checks = self.transform_block( graph, block) n_need_exc_matching_blocks += need_exc_matching n_gen_exc_checks += gen_exc_checks cleanup_graph(graph) return n_need_exc_matching_blocks, n_gen_exc_checks
def test_tweak_generator_graph(self): def f(n, x, y, z): z *= 10 yield n + 1 z -= 10 # space = FlowObjSpace() graph = space.build_flow(f, tweak_for_generator=False) GeneratorIterator = make_generatoriterator_class(graph) replace_graph_with_bootstrap(GeneratorIterator, graph) func1 = attach_next_method(GeneratorIterator, graph) if option.view: graph.show() # assert func1._generator_next_method_of_ is GeneratorIterator assert hasattr(GeneratorIterator, 'next') # graph_next = space.build_flow(GeneratorIterator.next.im_func) join_blocks(graph_next) if option.view: graph_next.show() # graph1 = space.build_flow(func1, tweak_for_generator=False) tweak_generator_body_graph(GeneratorIterator.Entry, graph1) if option.view: graph1.show()
def remove_asserts(translator, graphs): rtyper = translator.rtyper clsdef = translator.annotator.bookkeeper.getuniqueclassdef(AssertionError) r_AssertionError = rclass.getclassrepr(rtyper, clsdef) ll_AssertionError = r_AssertionError.convert_const(AssertionError) total_count = [0, 0] for graph in graphs: count = 0 morework = True while morework: morework = False eliminate_empty_blocks(graph) join_blocks(graph) for link in graph.iterlinks(): if (link.target is graph.exceptblock and isinstance(link.args[0], Constant) and link.args[0].value == ll_AssertionError): if kill_assertion_link(graph, link): count += 1 morework = True break else: total_count[0] += 1 if translator.config.translation.verbose: log.removeassert("cannot remove an assert from %s" % (graph.name,)) if count: # now melt away the (hopefully) dead operation that compute # the condition total_count[1] += count if translator.config.translation.verbose: log.removeassert("removed %d asserts in %s" % (count, graph.name)) checkgraph(graph) #transform_dead_op_vars(graph, translator) log.removeassert("Could not remove %d asserts, but removed %d asserts." % tuple(total_count))
def create_exception_handling(self, graph, always_exc_clear=False): """After an exception in a direct_call (or indirect_call), that is not caught by an explicit except statement, we need to reraise the exception. So after this direct_call we need to test if an exception had occurred. If so, we return from the current graph with a special value (False/-1/-1.0/null). Because of the added exitswitch we need an additional block. """ if hasattr(graph, 'exceptiontransformed'): assert self.same_obj(self.exc_data_ptr, graph.exceptiontransformed) return else: self.raise_analyzer.analyze_direct_call(graph) graph.exceptiontransformed = self.exc_data_ptr self.always_exc_clear = always_exc_clear join_blocks(graph) # collect the blocks before changing them n_need_exc_matching_blocks = 0 n_gen_exc_checks = 0 for block in list(graph.iterblocks()): self.replace_stack_unwind(block) self.replace_fetch_restore_operations(block) need_exc_matching, gen_exc_checks = self.transform_block(graph, block) n_need_exc_matching_blocks += need_exc_matching n_gen_exc_checks += gen_exc_checks self.transform_except_block(graph, graph.exceptblock) cleanup_graph(graph) removenoops.remove_superfluous_keep_alive(graph) return n_need_exc_matching_blocks, n_gen_exc_checks
def test_wearetranslated(self): x = self.codetest(self.wearetranslated) from pypy.translator.simplify import join_blocks join_blocks(x) # check that 'x' is an empty graph assert len(x.startblock.operations) == 0 assert len(x.startblock.exits) == 1 assert x.startblock.exits[0].target is x.returnblock
def test_specialcases(self): x = self.codetest(self.specialcases) from pypy.translator.simplify import join_blocks join_blocks(x) assert len(x.startblock.operations) == 14 for op in x.startblock.operations: assert op.opname in ['lt', 'le', 'eq', 'ne', 'gt', 'ge', 'is_', 'xor'] assert len(op.args) == 2 assert op.args[1].value == 3
def test_specialcases(self): x = self.codetest(self.specialcases) from pypy.translator.simplify import join_blocks join_blocks(x) assert len(x.startblock.operations) == 14 for op in x.startblock.operations: assert op.opname in ["lt", "le", "eq", "ne", "gt", "ge", "is_", "xor"] assert len(op.args) == 2 assert op.args[1].value == 3
def virtualize_mallocs(translator, graphs, verbose=False): newgraphs = graphs[:] mallocv = MallocVirtualizer(newgraphs, translator.rtyper, verbose) while mallocv.remove_mallocs_once(): pass for graph in newgraphs: checkgraph(graph) join_blocks(graph) assert newgraphs[:len(graphs)] == graphs del newgraphs[:len(graphs)] translator.graphs.extend(newgraphs)
def remove_duplicate_casts(graph, translator): simplify.join_blocks(graph) num_removed = 0 # remove chains of casts for block in graph.iterblocks(): comes_from = {} for op in block.operations: if op.opname == "cast_pointer": if op.args[0] in comes_from: from_var = comes_from[op.args[0]] comes_from[op.result] = from_var if from_var.concretetype == op.result.concretetype: op.opname = "same_as" op.args = [from_var] num_removed += 1 else: op.args = [from_var] else: comes_from[op.result] = op.args[0] if num_removed: remove_same_as(graph) # remove duplicate casts for block in graph.iterblocks(): available = {} for op in block.operations: if op.opname == "cast_pointer": key = (op.args[0], op.result.concretetype) if key in available: op.opname = "same_as" op.args = [available[key]] num_removed += 1 else: available[key] = op.result elif op.opname == 'resume_point': available.clear() if num_removed: remove_same_as(graph) # remove casts with unused results for block in graph.iterblocks(): used = {} for link in block.exits: for arg in link.args: used[arg] = True for i, op in list(enumerate(block.operations))[::-1]: if op.opname == "cast_pointer" and op.result not in used: del block.operations[i] num_removed += 1 else: for arg in op.args: used[arg] = True if translator.config.translation.verbose: log.removecasts( "removed %s cast_pointers in %s" % (num_removed, graph.name)) return num_removed
def remove_duplicate_casts(graph, translator): simplify.join_blocks(graph) num_removed = 0 # remove chains of casts for block in graph.iterblocks(): comes_from = {} for op in block.operations: if op.opname == "cast_pointer": if op.args[0] in comes_from: from_var = comes_from[op.args[0]] comes_from[op.result] = from_var if from_var.concretetype == op.result.concretetype: op.opname = "same_as" op.args = [from_var] num_removed += 1 else: op.args = [from_var] else: comes_from[op.result] = op.args[0] if num_removed: remove_same_as(graph) # remove duplicate casts for block in graph.iterblocks(): available = {} for op in block.operations: if op.opname == "cast_pointer": key = (op.args[0], op.result.concretetype) if key in available: op.opname = "same_as" op.args = [available[key]] num_removed += 1 else: available[key] = op.result elif op.opname == 'resume_point': available.clear() if num_removed: remove_same_as(graph) # remove casts with unused results for block in graph.iterblocks(): used = {} for link in block.exits: for arg in link.args: used[arg] = True for i, op in list(enumerate(block.operations))[::-1]: if op.opname == "cast_pointer" and op.result not in used: del block.operations[i] num_removed += 1 else: for arg in op.args: used[arg] = True if translator.config.translation.verbose: log.removecasts("removed %s cast_pointers in %s" % (num_removed, graph.name)) return num_removed
def transform_func(fn, inputtypes): t = TranslationContext() t.buildannotator().build_types(fn, inputtypes) t.buildrtyper().specialize() if conftest.option.view: t.view() g = graphof(t, fn) etrafo = exceptiontransform.ExceptionTransformer(t) etrafo.create_exception_handling(g) join_blocks(g) if conftest.option.view: t.view() return t, g
def transform_func(self, fn, inputtypes, backendopt=False): t = TranslationContext() t.buildannotator().build_types(fn, inputtypes) t.buildrtyper(type_system=self.type_system).specialize() if conftest.option.view: t.view() if backendopt: backend_optimizations(t) g = graphof(t, fn) etrafo = exceptiontransform.ExceptionTransformer(t) etrafo.create_exception_handling(g) join_blocks(g) if conftest.option.view: t.view() return t, g
def __init__(self, translator, graph, inline_func, lltype_to_classdef, inline_guarded_calls=False, inline_guarded_calls_no_matter_what=False, raise_analyzer=None, call_count_pred=None): BaseInliner.__init__(self, translator, graph, lltype_to_classdef, inline_guarded_calls, inline_guarded_calls_no_matter_what, raise_analyzer, call_count_pred) self.inline_func = inline_func # to simplify exception matching join_blocks(graph) # find callsites *after* joining blocks... callsites = find_callsites(graph, inline_func) self.block_to_index = {} for g, block, i in callsites: self.block_to_index.setdefault(block, {})[i] = g
def remove_tail_calls_to_self(translator, graph): entrymap = mkentrymap(graph) changed = False for link in entrymap[graph.returnblock]: block = link.prevblock if (len(block.exits) == 1 and len(block.operations) > 0 and block.operations[-1].opname == 'direct_call' and block.operations[-1].result == link.args[0]): call = get_graph(block.operations[-1].args[0], translator) print "getgraph", graph if graph is graph: _remove_tail_call(translator, graph, block) changed = True if changed: from pypy.translator import simplify checkgraph(graph) simplify.remove_identical_vars(graph) simplify.eliminate_empty_blocks(graph) simplify.join_blocks(graph)
def __init__(self, translator, graph, inline_func, lltype_to_classdef, inline_guarded_calls=False, inline_guarded_calls_no_matter_what=False, raise_analyzer=None, call_count_pred=None, cleanup=True): BaseInliner.__init__(self, translator, graph, lltype_to_classdef, inline_guarded_calls, inline_guarded_calls_no_matter_what, raise_analyzer, call_count_pred, cleanup) self.inline_func = inline_func # to simplify exception matching join_blocks(graph) # find callsites *after* joining blocks... callsites = find_callsites(graph, inline_func) self.block_to_index = {} for g, block, i in callsites: self.block_to_index.setdefault(block, {})[i] = g
def remove_asserts(translator, graphs): rtyper = translator.rtyper clsdef = translator.annotator.bookkeeper.getuniqueclassdef(AssertionError) r_AssertionError = rclass.getclassrepr(rtyper, clsdef) ll_AssertionError = r_AssertionError.convert_const(AssertionError) total_count = [0, 0] for graph in graphs: count = 0 morework = True while morework: morework = False eliminate_empty_blocks(graph) join_blocks(graph) for link in graph.iterlinks(): if (link.target is graph.exceptblock and isinstance(link.args[0], Constant) and link.args[0].value == ll_AssertionError): if kill_assertion_link(graph, link): count += 1 morework = True break else: total_count[0] += 1 if translator.config.translation.verbose: log.removeassert( "cannot remove an assert from %s" % (graph.name, )) if count: # now melt away the (hopefully) dead operation that compute # the condition total_count[1] += count if translator.config.translation.verbose: log.removeassert("removed %d asserts in %s" % (count, graph.name)) checkgraph(graph) #transform_dead_op_vars(graph, translator) log.removeassert("Could not remove %d asserts, but removed %d asserts." % tuple(total_count))