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']) gc_returning_calls = len([op for op in block.operations if op.opname in ('direct_call', 'indirect_call') and var_needsgc(op.result)]) pop_alives = len([op for op in block.operations if op.opname == 'gc_pop_alive']) if pop_alives == len(block.operations): # it's a block we inserted return assert not block.canraise for link in block.exits: refs_out = 0 for v2 in link.target.inputargs: if var_needsgc(v2) and not is_borrowed(v2): refs_out += 1 pushes = push_alives + gc_returning_calls assert refs_in + pushes == 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']) gc_returning_calls = len([ op for op in block.operations if op.opname in ('direct_call', 'indirect_call') and var_needsgc(op.result) ]) pop_alives = len( [op for op in block.operations if op.opname == 'gc_pop_alive']) if pop_alives == len(block.operations): # it's a block we inserted return assert not block.canraise for link in block.exits: refs_out = 0 for v2 in link.target.inputargs: if var_needsgc(v2) and not is_borrowed(v2): refs_out += 1 pushes = push_alives + gc_returning_calls assert refs_in + pushes == pop_alives + refs_out
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 not block.canraise 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 self.curr_block = 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 not block.canraise 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 self.curr_block = None
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 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)