def transform_block(self, block, is_borrowed): llops = LowLevelOpList() #self.curr_block = block self.livevars = [ var for var in block.inputargs if var_needsgc(var) and not is_borrowed(var) ] allvars = [var for var in block.getvariables() if var_needsgc(var)] self.var_last_needed_in = dict.fromkeys(allvars, 0) for i, op in enumerate(block.operations): for var in op.args: if not var_needsgc(var): continue self.var_last_needed_in[var] = i for link in block.exits: for var in link.args: if not var_needsgc(var): continue self.var_last_needed_in[var] = len(block.operations) + 1 for i, op in enumerate(block.operations): hop = GcHighLevelOp(self, op, i, llops) hop.dispatch() if len(block.exits) != 0: # i.e not the return block assert block.exitswitch is not c_last_exception deadinallexits = set(self.livevars) for link in block.exits: deadinallexits.difference_update(set(link.args)) for var in deadinallexits: self.pop_alive(var, llops) for link in block.exits: livecounts = dict.fromkeys( set(self.livevars) - deadinallexits, 1) for v, v2 in zip(link.args, link.target.inputargs): if is_borrowed(v2): continue if v in livecounts: livecounts[v] -= 1 elif var_needsgc(v): # 'v' is typically a Constant here, but it can be # a borrowed variable going into a non-borrowed one livecounts[v] = -1 self.links_to_split[link] = livecounts block.operations[:] = llops self.livevars = None self.var_last_needed_in = None
def transform_block(self, block, is_borrowed): llops = LowLevelOpList() #self.curr_block = block self.livevars = [var for var in block.inputargs if var_needsgc(var) and not is_borrowed(var)] allvars = [var for var in block.getvariables() if var_needsgc(var)] self.var_last_needed_in = dict.fromkeys(allvars, 0) for i, op in enumerate(block.operations): for var in op.args: if not var_needsgc(var): continue self.var_last_needed_in[var] = i for link in block.exits: for var in link.args: if not var_needsgc(var): continue self.var_last_needed_in[var] = len(block.operations) + 1 for i, op in enumerate(block.operations): hop = GcHighLevelOp(self, op, i, llops) hop.dispatch() if len(block.exits) != 0: # i.e not the return block assert block.exitswitch is not c_last_exception deadinallexits = sets.Set(self.livevars) for link in block.exits: deadinallexits.difference_update(sets.Set(link.args)) for var in deadinallexits: self.pop_alive(var, llops) for link in block.exits: livecounts = dict.fromkeys(sets.Set(self.livevars) - deadinallexits, 1) for v, v2 in zip(link.args, link.target.inputargs): if is_borrowed(v2): continue if v in livecounts: livecounts[v] -= 1 elif var_needsgc(v): # 'v' is typically a Constant here, but it can be # a borrowed variable going into a non-borrowed one livecounts[v] = -1 self.links_to_split[link] = livecounts block.operations[:] = llops self.livevars = None self.var_last_needed_in = None
def checkblock(block, is_borrowed, is_start_block): if block.operations == (): # a return/exception block -- don't want to think about them # (even though the test passes for somewhat accidental reasons) return if is_start_block: refs_in = 0 else: refs_in = len([ v for v in block.inputargs if isinstance(v, Variable) and var_needsgc(v) and not is_borrowed(v) ]) push_alives = len( [op for op in block.operations if op.opname == 'gc_push_alive']) pyobj_push_alives = len( [op for op in block.operations if op.opname == 'gc_push_alive_pyobj']) # implicit_pyobj_pushalives included calls to things that return pyobject* implicit_pyobj_pushalives = len([ op for op in block.operations if var_ispyobj(op.result) and op.opname not in ('getfield', 'getarrayitem', 'same_as') ]) nonpyobj_gc_returning_calls = len([ op for op in block.operations if op.opname in ('direct_call', 'indirect_call') and var_needsgc(op.result) and not var_ispyobj(op.result) ]) pop_alives = len( [op for op in block.operations if op.opname == 'gc_pop_alive']) pyobj_pop_alives = len( [op for op in block.operations if op.opname == 'gc_pop_alive_pyobj']) if pop_alives == len(block.operations): # it's a block we inserted return for link in block.exits: assert block.exitswitch is not c_last_exception refs_out = 0 for v2 in link.target.inputargs: if var_needsgc(v2) and not is_borrowed(v2): refs_out += 1 pyobj_pushes = pyobj_push_alives + implicit_pyobj_pushalives nonpyobj_pushes = push_alives + nonpyobj_gc_returning_calls assert refs_in + pyobj_pushes + nonpyobj_pushes == pop_alives + pyobj_pop_alives + refs_out
def checkblock(block, is_borrowed, is_start_block): if block.operations == (): # a return/exception block -- don't want to think about them # (even though the test passes for somewhat accidental reasons) return if is_start_block: refs_in = 0 else: refs_in = len([v for v in block.inputargs if isinstance(v, Variable) and var_needsgc(v) and not is_borrowed(v)]) push_alives = len([op for op in block.operations if op.opname == 'gc_push_alive']) pyobj_push_alives = len([op for op in block.operations if op.opname == 'gc_push_alive_pyobj']) # implicit_pyobj_pushalives included calls to things that return pyobject* implicit_pyobj_pushalives = len([op for op in block.operations if var_ispyobj(op.result) and op.opname not in ('getfield', 'getarrayitem', 'same_as')]) nonpyobj_gc_returning_calls = len([op for op in block.operations if op.opname in ('direct_call', 'indirect_call') and var_needsgc(op.result) and not var_ispyobj(op.result)]) pop_alives = len([op for op in block.operations if op.opname == 'gc_pop_alive']) pyobj_pop_alives = len([op for op in block.operations if op.opname == 'gc_pop_alive_pyobj']) if pop_alives == len(block.operations): # it's a block we inserted return for link in block.exits: assert block.exitswitch is not c_last_exception refs_out = 0 for v2 in link.target.inputargs: if var_needsgc(v2) and not is_borrowed(v2): refs_out += 1 pyobj_pushes = pyobj_push_alives + implicit_pyobj_pushalives nonpyobj_pushes = push_alives + nonpyobj_gc_returning_calls assert refs_in + pyobj_pushes + nonpyobj_pushes == pop_alives + pyobj_pop_alives + refs_out
def dispatch(self): gct = self.gctransformer opname = self.spaceop.opname v_result = self.spaceop.result meth = getattr(gct, 'gct_' + opname, gct.default) meth(self) if var_needsgc(v_result): gct.livevars.append(v_result) if var_ispyobj(v_result): if opname in ('getfield', 'getarrayitem', 'same_as', 'cast_pointer', 'getsubstruct', 'getinteriorfield'): # XXX more operations? gct.push_alive(v_result, self.llops) elif opname not in ('direct_call', 'indirect_call'): gct.push_alive(v_result, self.llops)
def var_needs_set_transform(self, var): return var_needsgc(var)