def test_regalloc_exitswitch_2(self): v1 = Variable(); v1.concretetype = rclass.CLASSTYPE v2 = Variable(); v2.concretetype = rclass.CLASSTYPE v3 = Variable(); v3.concretetype = rclass.CLASSTYPE v4 = Variable(); v4.concretetype = rclass.CLASSTYPE block = Block([]) block.operations = [ SpaceOperation('res_call', [], v1), SpaceOperation('-live-', [], None), ] graph = FunctionGraph('f', block, v4) exclink = Link([v2], graph.returnblock) exclink.llexitcase = 123 # normally an exception class exclink.last_exception = v2 exclink.last_exc_value = "unused" block.exitswitch = c_last_exception block.closeblock(Link([v1], graph.returnblock), exclink) # self.check_assembler(graph, """ res_call -> %i0 -live- catch_exception L1 int_return %i0 --- L1: goto_if_exception_mismatch $123, L2 last_exception -> %i0 int_return %i0 --- L2: reraise """)
def copy_link(self, link, prevblock): newargs = [self.get_new_name(a) for a in link.args] + self.passon_vars(prevblock) newlink = Link(newargs, self.copy_block(link.target), link.exitcase) newlink.last_exception = self.get_new_name(link.last_exception) newlink.last_exc_value = self.get_new_name(link.last_exc_value) if hasattr(link, 'llexitcase'): newlink.llexitcase = link.llexitcase return newlink
def generic_exception_matching(self, afterblock, copiedexceptblock): #XXXXX don't look: insert blocks that do exception matching #for the cases where direct matching did not work exc_match = Constant( self.translator.rtyper.getexceptiondata().fn_exception_match) exc_match.concretetype = typeOf(exc_match.value) blocks = [] for i, link in enumerate(afterblock.exits[1:]): etype = copyvar(None, copiedexceptblock.inputargs[0]) evalue = copyvar(None, copiedexceptblock.inputargs[1]) passon_vars = self.passon_vars(i) block = Block([etype, evalue] + passon_vars) res = Variable() res.concretetype = Bool cexitcase = Constant(link.llexitcase) cexitcase.concretetype = typeOf(cexitcase.value) args = [exc_match, etype, cexitcase] block.operations.append(SpaceOperation("direct_call", args, res)) block.exitswitch = res linkargs = self.find_args_in_exceptional_case(link, link.target, etype, evalue, afterblock, passon_vars) l = Link(linkargs, link.target) l.prevblock = block l.exitcase = True l.llexitcase = True block.closeblock(l) if i > 0: l = Link(blocks[-1].inputargs, block) l.exitcase = False l.llexitcase = False blocks[-1].recloseblock(l, *blocks[-1].exits) blocks.append(block) blocks[-1].recloseblock(*blocks[-1].exits[:1]) blocks[-1].operations = [] blocks[-1].exitswitch = None blocks[-1].exits[0].exitcase = None del blocks[-1].exits[0].llexitcase linkargs = copiedexceptblock.inputargs copiedexceptblock.recloseblock(Link(linkargs, blocks[0])) copiedexceptblock.operations += self.generate_keepalive(linkargs)
def test_regalloc_exitswitch_2(self): v1 = Variable() v1.concretetype = rclass.CLASSTYPE v2 = Variable() v2.concretetype = rclass.CLASSTYPE v3 = Variable() v3.concretetype = rclass.CLASSTYPE v4 = Variable() v4.concretetype = rclass.CLASSTYPE block = Block([]) block.operations = [ SpaceOperation('res_call', [], v1), SpaceOperation('-live-', [], None), ] graph = FunctionGraph('f', block, v4) exclink = Link([v2], graph.returnblock) exclink.llexitcase = 123 # normally an exception class exclink.last_exception = v2 exclink.last_exc_value = "unused" block.exitswitch = c_last_exception block.closeblock(Link([v1], graph.returnblock), exclink) # self.check_assembler( graph, """ res_call -> %i0 -live- catch_exception L1 int_return %i0 --- L1: goto_if_exception_mismatch $123, L2 last_exception -> %i0 int_return %i0 --- L2: reraise """)
def insert_integer_search(self, block, cases, defaultlink, blockset, range_start, range_stop): # fix the exit of the 'block' to check for the given remaining # 'cases', knowing that if we get there then the value must # be contained in range(range_start, range_stop). if not cases: assert defaultlink is not None block.exitswitch = None block.recloseblock(Link(defaultlink.args, defaultlink.target)) elif len(cases) == 1 and (defaultlink is None or range_start == range_stop-1): block.exitswitch = None block.recloseblock(cases.values()[0]) else: intvalues = cases.keys() intvalues.sort() if len(intvalues) <= 3: # not much point in being clever with no more than 3 cases intval = intvalues[-1] remainingcases = cases.copy() link = remainingcases.pop(intval) c_intval = inputconst(lltype.Signed, intval) v = self.genop(block, 'int_eq', [block.exitswitch, c_intval], resulttype=lltype.Bool, red=True) link.exitcase = True link.llexitcase = True falseblock = Block([]) falseblock.exitswitch = block.exitswitch blockset[falseblock] = False falselink = Link([], falseblock) falselink.exitcase = False falselink.llexitcase = False block.exitswitch = v block.recloseblock(falselink, link) if defaultlink is None or intval == range_stop-1: range_stop = intval self.insert_integer_search(falseblock, remainingcases, defaultlink, blockset, range_start, range_stop) else: intval = intvalues[len(intvalues) // 2] c_intval = inputconst(lltype.Signed, intval) v = self.genop(block, 'int_ge', [block.exitswitch, c_intval], resulttype=lltype.Bool, red=True) falseblock = Block([]) falseblock.exitswitch = block.exitswitch trueblock = Block([]) trueblock.exitswitch = block.exitswitch blockset[falseblock] = False blockset[trueblock] = False falselink = Link([], falseblock) falselink.exitcase = False falselink.llexitcase = False truelink = Link([], trueblock) truelink.exitcase = True truelink.llexitcase = True block.exitswitch = v block.recloseblock(falselink, truelink) falsecases = {} truecases = {} for intval1, link1 in cases.items(): if intval1 < intval: falsecases[intval1] = link1 else: truecases[intval1] = link1 self.insert_integer_search(falseblock, falsecases, defaultlink, blockset, range_start, intval) self.insert_integer_search(trueblock, truecases, defaultlink, blockset, intval, range_stop)