Author: Armin Rigo <ar...@tunes.org> Branch: keys_with_hash Changeset: r79348:11a2870d60ff Date: 2015-09-01 13:15 +0200 http://bitbucket.org/pypy/pypy/changeset/11a2870d60ff/
Log: Split this huge function into 6 subfunctions diff --git a/rpython/rtyper/rdict.py b/rpython/rtyper/rdict.py --- a/rpython/rtyper/rdict.py +++ b/rpython/rtyper/rdict.py @@ -72,21 +72,14 @@ return hop.gendirectcall(self.ll_dictiter, citerptr, v_dict) def rtype_next(self, hop): - variant = self.variant v_iter, = hop.inputargs(self) # record that we know about these two possible exceptions hop.has_implicit_exception(StopIteration) hop.has_implicit_exception(RuntimeError) hop.exception_is_here() v_index = hop.gendirectcall(self._ll_dictnext, v_iter) - if ((variant == 'items' and hop.r_result.lowleveltype != lltype.Void) or - variant == 'keys_with_hash' or variant == 'items_with_hash'): - # this allocates the tuple for the result, directly in the function - # where it will be used (likely). This will let it be removed. - c1 = hop.inputconst(lltype.Void, hop.r_result.lowleveltype.TO) - cflags = hop.inputconst(lltype.Void, {'flavor': 'gc'}) - v_result = hop.genop('malloc', [c1, cflags], - resulttype = hop.r_result.lowleveltype) + # + # read 'iter.dict.entries' DICT = self.lowleveltype.TO.dict c_dict = hop.inputconst(lltype.Void, 'dict') v_dict = hop.genop('getfield', [v_iter, c_dict], resulttype=DICT) @@ -94,48 +87,61 @@ c_entries = hop.inputconst(lltype.Void, 'entries') v_entries = hop.genop('getfield', [v_dict, c_entries], resulttype=ENTRIES) - if variant != 'values': - KEY = ENTRIES.TO.OF.key - c_key = hop.inputconst(lltype.Void, 'key') - v_key = hop.genop('getinteriorfield', [v_entries, v_index, c_key], - resulttype=KEY) - if (variant == 'values' or variant == 'items' - or variant == 'items_with_hash'): - VALUE = ENTRIES.TO.OF.value - c_value = hop.inputconst(lltype.Void, 'value') - v_value = hop.genop('getinteriorfield', [v_entries,v_index,c_value], - resulttype=VALUE) - if variant == 'keys_with_hash' or variant == 'items_with_hash': - v_hash = hop.gendirectcall(ENTRIES.TO.hash, v_entries, v_index) - # - if variant == 'keys' or variant == 'reversed': - return self.r_dict.recast_key(hop.llops, v_key) - elif variant == 'values': - return self.r_dict.recast_value(hop.llops, v_value) - elif variant == 'keys_with_hash': - ITEM0 = v_result.concretetype.TO.item0 - if ITEM0 != v_key.concretetype: - v_key = hop.genop('cast_pointer', [v_key], resulttype=ITEM0) - c_item0 = hop.inputconst(lltype.Void, 'item0') - c_item1 = hop.inputconst(lltype.Void, 'item1') - hop.genop('setfield', [v_result, c_item0, v_key]) - hop.genop('setfield', [v_result, c_item1, v_hash]) - return v_result - elif hop.r_result.lowleveltype == lltype.Void: + # call the correct variant_*() method + method = getattr(self, 'variant_' + self.variant) + return method(hop, ENTRIES, v_entries, v_index) + + def get_tuple_result(self, hop, items_v): + # this allocates the tuple for the result, directly in the function + # where it will be used (likely). This will let it be removed. + if hop.r_result.lowleveltype is lltype.Void: return hop.inputconst(lltype.Void, None) - else: - assert variant == 'items' or variant == 'items_with_hash' - ITEM0 = v_result.concretetype.TO.item0 - ITEM1 = v_result.concretetype.TO.item1 - if ITEM0 != v_key.concretetype: - v_key = hop.genop('cast_pointer', [v_key], resulttype=ITEM0) - if ITEM1 != v_value.concretetype: - v_value = hop.genop('cast_pointer', [v_value], resulttype=ITEM1) - c_item0 = hop.inputconst(lltype.Void, 'item0') - c_item1 = hop.inputconst(lltype.Void, 'item1') - hop.genop('setfield', [v_result, c_item0, v_key]) - hop.genop('setfield', [v_result, c_item1, v_value]) - if variant == 'items_with_hash': - c_item2 = hop.inputconst(lltype.Void, 'item2') - hop.genop('setfield', [v_result, c_item2, v_hash]) - return v_result + c1 = hop.inputconst(lltype.Void, hop.r_result.lowleveltype.TO) + cflags = hop.inputconst(lltype.Void, {'flavor': 'gc'}) + v_result = hop.genop('malloc', [c1, cflags], + resulttype = hop.r_result.lowleveltype) + for i, v_item in enumerate(items_v): + ITEM = getattr(v_result.concretetype.TO, 'item%d' % i) + if ITEM != v_item.concretetype: + assert isinstance(ITEM, lltype.Ptr) + v_item = hop.genop('cast_pointer', [v_item], resulttype=ITEM) + c_item = hop.inputconst(lltype.Void, 'item%d' % i) + hop.genop('setfield', [v_result, c_item, v_item]) + return v_result + + def variant_keys(self, hop, ENTRIES, v_entries, v_index): + KEY = ENTRIES.TO.OF.key + c_key = hop.inputconst(lltype.Void, 'key') + v_key = hop.genop('getinteriorfield', [v_entries, v_index, c_key], + resulttype=KEY) + return self.r_dict.recast_key(hop.llops, v_key) + + variant_reversed = variant_keys + + def variant_values(self, hop, ENTRIES, v_entries, v_index): + VALUE = ENTRIES.TO.OF.value + c_value = hop.inputconst(lltype.Void, 'value') + v_value = hop.genop('getinteriorfield', [v_entries,v_index,c_value], + resulttype=VALUE) + return self.r_dict.recast_value(hop.llops, v_value) + + def variant_items(self, hop, ENTRIES, v_entries, v_index): + v_key = self.variant_keys(hop, ENTRIES, v_entries, v_index) + v_value = self.variant_values(hop, ENTRIES, v_entries, v_index) + return self.get_tuple_result(hop, (v_key, v_value)) + + def variant_hashes(self, hop, ENTRIES, v_entries, v_index): + # there is not really a variant 'hashes', but this method is + # convenient for the following variants + return hop.gendirectcall(ENTRIES.TO.hash, v_entries, v_index) + + def variant_keys_with_hash(self, hop, ENTRIES, v_entries, v_index): + v_key = self.variant_keys(hop, ENTRIES, v_entries, v_index) + v_hash = self.variant_hashes(hop, ENTRIES, v_entries, v_index) + return self.get_tuple_result(hop, (v_key, v_hash)) + + def variant_items_with_hash(self, hop, ENTRIES, v_entries, v_index): + v_key = self.variant_keys(hop, ENTRIES, v_entries, v_index) + v_value = self.variant_values(hop, ENTRIES, v_entries, v_index) + v_hash = self.variant_hashes(hop, ENTRIES, v_entries, v_index) + return self.get_tuple_result(hop, (v_key, v_value, v_hash)) _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit