def naive_split_block(self, block, position): newblock = Block([]) newblock.operations = block.operations[position:] del block.operations[position:] newblock.exitswitch = block.exitswitch block.exitswitch = None newblock.recloseblock(*block.exits) block.recloseblock(Link([], newblock)) return newblock
def handle_after_residual_call_details(self, block, pos, newops, blockset, withexc, oop = False): dopts = {'withexc': withexc, 'oop': oop } copts = Constant(dopts, lltype.Void) v_flags = self.genop(newops, 'after_residual_call', [copts], resulttype=lltype.Signed, red=True) residual_fetch_index = len(newops) self.genop(newops, 'residual_fetch', [v_flags, copts]) residual_fetch_pos = pos+residual_fetch_index block.operations[pos:pos+1] = newops link_t = split_block(self.hannotator, block, residual_fetch_pos) nextblock = link_t.target blockset[nextblock] = False i_flags = link_t.args.index(v_flags) reds, greens = self.sort_by_color(link_t.args) self.genop(block, 'save_locals', reds) SPLIT_FOR_ZERO = False if SPLIT_FOR_ZERO: promoteblock = Block([copyvar(self.hannotator, v) for v in link_t.args]) link_f = Link(link_t.args, promoteblock) promoteblock.recloseblock(Link(promoteblock.inputargs, nextblock)) blockset[promoteblock] = False v_flags2 = promoteblock.inputargs[i_flags] else: promoteblock = block v_flags2 = v_flags # if there is no global merge point, this 'promote' will actually # always see a constant red box v_finished_flag = self.genop(promoteblock, 'promote', [v_flags2], resulttype = lltype.Bool) self.go_to_dispatcher_if(promoteblock, v_finished_flag) if SPLIT_FOR_ZERO: c_zero = inputconst(lltype.Signed, 0) link_t.args = link_t.args[:] link_t.args[i_flags] = c_zero resumepoint = self.get_resume_point(promoteblock) c_resumepoint = inputconst(lltype.Signed, resumepoint) v_is_zero = self.genop(block, 'int_eq', [v_flags, c_zero], resulttype=lltype.Bool, red=True) v_is_zero = self.genop(block, 'split', [v_is_zero, c_resumepoint] + greens, resulttype = lltype.Bool) block.exitswitch = v_is_zero link_t.exitcase = True link_f.exitcase = False block.recloseblock(link_f, link_t)
def transform_jump_to_except_block(self, graph, entrymap, link): reraise = self.comes_from_last_exception(entrymap, link) result = Variable() result.concretetype = lltype.Void block = Block([copyvar(None, v) for v in graph.exceptblock.inputargs]) if reraise: block.operations = [SpaceOperation("direct_call", [self.rpyexc_reraise_ptr] + block.inputargs, result)] else: block.operations = [ SpaceOperation("direct_call", [self.rpyexc_raise_ptr] + block.inputargs, result), SpaceOperation("debug_record_traceback", [], varoftype(lltype.Void)), ] link.target = block RETTYPE = graph.returnblock.inputargs[0].concretetype l = Link([error_constant(RETTYPE)], graph.returnblock) block.recloseblock(l)
def transform_jump_to_except_block(self, graph, entrymap, link): reraise = self.comes_from_last_exception(entrymap, link) result = Variable() result.concretetype = lltype.Void block = Block([copyvar(None, v) for v in graph.exceptblock.inputargs]) if reraise: block.operations = [ SpaceOperation("direct_call", [self.rpyexc_reraise_ptr] + block.inputargs, result), ] else: block.operations = [ SpaceOperation("direct_call", [self.rpyexc_raise_ptr] + block.inputargs, result), SpaceOperation('debug_record_traceback', [], varoftype(lltype.Void)), ] link.target = block RETTYPE = graph.returnblock.inputargs[0].concretetype l = Link([error_constant(RETTYPE)], graph.returnblock) block.recloseblock(l)
def handle_red_call(self, block, pos, withexc, color='red'): link = split_block(self.hannotator, block, pos+1) op = block.operations.pop(pos) #if op.opname == 'direct_call': # f = open('LOG', 'a') # print >> f, color, op.args[0].value # f.close() assert len(block.operations) == pos nextblock = link.target linkargs = link.args varsalive = list(linkargs) if color != 'gray': # the result will be either passed as an extra local 0 # by the caller, or restored by a restore_local try: index = varsalive.index(op.result) except ValueError: linkargs.insert(0, op.result) v_result = copyvar(self.hannotator, op.result) nextblock.inputargs.insert(0, v_result) else: del varsalive[index] old_v_result = linkargs.pop(index) linkargs.insert(0, old_v_result) v_result = nextblock.inputargs.pop(index) nextblock.inputargs.insert(0, v_result) else: if op.result in varsalive: index = varsalive.index(op.result) del varsalive[index] linkargs.pop(index) c_void = Constant(None, lltype.Void) linkargs.insert(0, c_void) v_result = nextblock.inputargs.pop(index) nextblock.inputargs.insert(0, v_result) reds, greens = self.sort_by_color(varsalive) blockset = {} blockset[block] = True # reachable from outside blockset[nextblock] = False v_func = op.args[0] hs_func = self.hannotator.binding(v_func) if hs_func.is_green(): constantblock = block nonconstantblock = None else: constantblock = Block([]) nonconstantblock = Block([]) blockset[constantblock] = False blockset[nonconstantblock] = False v_is_constant = self.genop(block, 'is_constant', [v_func], resulttype = lltype.Bool) self.genswitch(block, v_is_constant, true = constantblock, false = nonconstantblock) postconstantblock = self.naive_split_block(constantblock, len(constantblock.operations)) blockset[postconstantblock] = False self.make_call(constantblock, op, reds, color) conversionblock = nextblock if color == 'red': assert not self.hannotator.binding(op.result).is_green() elif color == 'yellow': conversionblock = Block([copyvar(self.hannotator, v) for v in nextblock.inputargs]) v0 = conversionblock.inputargs[0] already_green = self.hannotator.binding(op.result).is_green() assert already_green == self.hannotator.binding(v0).is_green() if not already_green: RESULT = self.hannotator.binding(v0).concretetype hs = hintmodel.SomeLLAbstractConstant(RESULT, {}) self.hannotator.bindings[v0] = hs conversionblock.closeblock(Link(conversionblock.inputargs, nextblock)) blockset[conversionblock] = False # to merge some of the possibly many return jitstates self.mergepoint_set[nextblock] = 'local' resumepoint = self.get_resume_point(conversionblock) c_resumepoint = inputconst(lltype.Signed, resumepoint) self.genop(postconstantblock, 'collect_split', [c_resumepoint] + greens) resumeblock = self.get_resume_point_link(conversionblock).target postconstantblock.recloseblock(Link([], resumeblock)) blockset[resumeblock] = True # reachable from outside if nonconstantblock is not None: nonconstantblock.recloseblock(Link(linkargs, nextblock)) v_res = self.handle_residual_call_details( nonconstantblock, 0, op, color, blockset, preserve_res = (color != 'gray'), withexc=withexc) SSA_to_SSI(blockset, self.hannotator)