Author: Maciej Fijalkowski <fij...@gmail.com> Branch: Changeset: r78346:32c897eb2152 Date: 2015-06-29 11:16 +0200 http://bitbucket.org/pypy/pypy/changeset/32c897eb2152/
Log: merge diff --git a/pypy/module/_cffi_backend/lib_obj.py b/pypy/module/_cffi_backend/lib_obj.py --- a/pypy/module/_cffi_backend/lib_obj.py +++ b/pypy/module/_cffi_backend/lib_obj.py @@ -175,6 +175,8 @@ return self.dir1(ignore_type=cffi_opcode.OP_GLOBAL_VAR) if is_getattr and attr == '__dict__': return self.full_dict_copy() + if is_getattr and attr == '__name__': + return self.descr_repr() raise oefmt(self.space.w_AttributeError, "cffi library '%s' has no function, constant " "or global variable named '%s'", diff --git a/pypy/module/_cffi_backend/src/parse_c_type.c b/pypy/module/_cffi_backend/src/parse_c_type.c --- a/pypy/module/_cffi_backend/src/parse_c_type.c +++ b/pypy/module/_cffi_backend/src/parse_c_type.c @@ -362,7 +362,7 @@ case TOK_INTEGER: errno = 0; -#ifndef MS_WIN32 +#ifndef _MSC_VER if (sizeof(length) > sizeof(unsigned long)) length = strtoull(tok->p, &endptr, 0); else diff --git a/pypy/module/_cffi_backend/test/test_recompiler.py b/pypy/module/_cffi_backend/test/test_recompiler.py --- a/pypy/module/_cffi_backend/test/test_recompiler.py +++ b/pypy/module/_cffi_backend/test/test_recompiler.py @@ -1011,3 +1011,4 @@ assert MYFOO == 42 assert hasattr(lib, '__dict__') assert lib.__all__ == ['MYFOO', 'mybar'] # but not 'myvar' + assert lib.__name__ == repr(lib) diff --git a/pypy/module/_io/test/test_io.py b/pypy/module/_io/test/test_io.py --- a/pypy/module/_io/test/test_io.py +++ b/pypy/module/_io/test/test_io.py @@ -420,6 +420,8 @@ {"mode": "w+b", "buffering": 0}, ]: print kwargs + if "b" not in kwargs["mode"]: + kwargs["encoding"] = "ascii" f = _io.open(self.tmpfile, **kwargs) f.close() raises(ValueError, f.flush) diff --git a/pypy/objspace/std/dictmultiobject.py b/pypy/objspace/std/dictmultiobject.py --- a/pypy/objspace/std/dictmultiobject.py +++ b/pypy/objspace/std/dictmultiobject.py @@ -711,7 +711,7 @@ next_item = _new_next('item') -def create_iterator_classes(dictimpl, override_next_item=None): +def create_iterator_classes(dictimpl): if not hasattr(dictimpl, 'wrapkey'): wrapkey = lambda space, key: key else: @@ -754,15 +754,12 @@ self.iterator = strategy.getiteritems(impl) BaseIteratorImplementation.__init__(self, space, strategy, impl) - if override_next_item is not None: - next_item_entry = override_next_item - else: - def next_item_entry(self): - for key, value in self.iterator: - return (wrapkey(self.space, key), - wrapvalue(self.space, value)) - else: - return None, None + def next_item_entry(self): + for key, value in self.iterator: + return (wrapkey(self.space, key), + wrapvalue(self.space, value)) + else: + return None, None class IterClassReversed(BaseKeyIterator): def __init__(self, space, strategy, impl): @@ -795,22 +792,7 @@ def rev_update1_dict_dict(self, w_dict, w_updatedict): # the logic is to call prepare_dict_update() after the first setitem(): # it gives the w_updatedict a chance to switch its strategy. - if override_next_item is not None: - # this is very similar to the general version, but the difference - # is that it is specialized to call a specific next_item() - iteritems = IterClassItems(self.space, self, w_dict) - w_key, w_value = iteritems.next_item() - if w_key is None: - return - w_updatedict.setitem(w_key, w_value) - w_updatedict.strategy.prepare_update(w_updatedict, - w_dict.length() - 1) - while True: - w_key, w_value = iteritems.next_item() - if w_key is None: - return - w_updatedict.setitem(w_key, w_value) - else: + if 1: # (preserve indentation) iteritems = self.getiteritems(w_dict) if not same_strategy(self, w_updatedict): # Different strategy. Try to copy one item of w_dict diff --git a/pypy/objspace/std/kwargsdict.py b/pypy/objspace/std/kwargsdict.py --- a/pypy/objspace/std/kwargsdict.py +++ b/pypy/objspace/std/kwargsdict.py @@ -166,19 +166,26 @@ return iter(self.unerase(w_dict.dstorage)[1]) def getiteritems(self, w_dict): - keys = self.unerase(w_dict.dstorage)[0] - return iter(range(len(keys))) + return Zip(*self.unerase(w_dict.dstorage)) wrapkey = _wrapkey -def next_item(self): - strategy = self.strategy - assert isinstance(strategy, KwargsDictStrategy) - for i in self.iterator: - keys, values_w = strategy.unerase(self.dictimplementation.dstorage) - return _wrapkey(self.space, keys[i]), values_w[i] - else: - return None, None +class Zip(object): + def __init__(self, list1, list2): + assert len(list1) == len(list2) + self.list1 = list1 + self.list2 = list2 + self.i = 0 -create_iterator_classes(KwargsDictStrategy, override_next_item=next_item) + def __iter__(self): + return self + + def next(self): + i = self.i + if i >= len(self.list1): + raise StopIteration + self.i = i + 1 + return (self.list1[i], self.list2[i]) + +create_iterator_classes(KwargsDictStrategy) diff --git a/pypy/objspace/std/test/test_kwargsdict.py b/pypy/objspace/std/test/test_kwargsdict.py --- a/pypy/objspace/std/test/test_kwargsdict.py +++ b/pypy/objspace/std/test/test_kwargsdict.py @@ -159,3 +159,10 @@ assert a == 3 assert "KwargsDictStrategy" in self.get_strategy(d) + def test_iteritems_bug(self): + def f(**args): + return args + + d = f(a=2, b=3, c=4) + for key, value in d.iteritems(): + None in d diff --git a/rpython/memory/gctransform/framework.py b/rpython/memory/gctransform/framework.py --- a/rpython/memory/gctransform/framework.py +++ b/rpython/memory/gctransform/framework.py @@ -52,21 +52,22 @@ return (op.opname in LL_OPERATIONS and LL_OPERATIONS[op.opname].canmallocgc) -def find_initializing_stores(collect_analyzer, graph): - from rpython.flowspace.model import mkentrymap - entrymap = mkentrymap(graph) - # a bit of a hackish analysis: if a block contains a malloc and check that - # the result is not zero, then the block following the True link will - # usually initialize the newly allocated object - result = set() - def find_in_block(block, mallocvars): +def propagate_no_write_barrier_needed(result, block, mallocvars, + collect_analyzer, entrymap, + startindex=0): + # We definitely know that no write barrier is needed in the 'block' + # for any of the variables in 'mallocvars'. Propagate this information + # forward. Note that "definitely know" implies that we just did either + # a fixed-size malloc (variable-size might require card marking), or + # that we just did a full write barrier (not just for card marking). + if 1: # keep indentation for i, op in enumerate(block.operations): + if i < startindex: + continue if op.opname in ("cast_pointer", "same_as"): if op.args[0] in mallocvars: mallocvars[op.result] = True elif op.opname in ("setfield", "setarrayitem", "setinteriorfield"): - # note that 'mallocvars' only tracks fixed-size mallocs, - # so no risk that they use card marking TYPE = op.args[-1].concretetype if (op.args[0] in mallocvars and isinstance(TYPE, lltype.Ptr) and @@ -83,7 +84,15 @@ if var in mallocvars: newmallocvars[exit.target.inputargs[i]] = True if newmallocvars: - find_in_block(exit.target, newmallocvars) + propagate_no_write_barrier_needed(result, exit.target, + newmallocvars, + collect_analyzer, entrymap) + +def find_initializing_stores(collect_analyzer, graph, entrymap): + # a bit of a hackish analysis: if a block contains a malloc and check that + # the result is not zero, then the block following the True link will + # usually initialize the newly allocated object + result = set() mallocnum = 0 blockset = set(graph.iterblocks()) while blockset: @@ -113,7 +122,8 @@ target = exit.target mallocvars = {target.inputargs[index]: True} mallocnum += 1 - find_in_block(target, mallocvars) + propagate_no_write_barrier_needed(result, target, mallocvars, + collect_analyzer, entrymap) #if result: # print "found %s initializing stores in %s" % (len(result), graph.name) return result @@ -698,8 +708,11 @@ " %s" % func) if self.write_barrier_ptr: + from rpython.flowspace.model import mkentrymap + self._entrymap = mkentrymap(graph) self.clean_sets = ( - find_initializing_stores(self.collect_analyzer, graph)) + find_initializing_stores(self.collect_analyzer, graph, + self._entrymap)) if self.gcdata.gc.can_optimize_clean_setarrayitems(): self.clean_sets = self.clean_sets.union( find_clean_setarrayitems(self.collect_analyzer, graph)) @@ -1269,6 +1282,17 @@ hop.genop("direct_call", [self.write_barrier_ptr, self.c_const_gc, v_structaddr]) + # we just did a full write barrier here, so we can use + # this helper to propagate this knowledge forward and + # avoid to repeat the write barrier. + if self.curr_block is not None: # for tests + assert self.curr_block.operations[hop.index] is hop.spaceop + propagate_no_write_barrier_needed(self.clean_sets, + self.curr_block, + {v_struct: True}, + self.collect_analyzer, + self._entrymap, + hop.index + 1) hop.rename('bare_' + opname) def transform_getfield_typeptr(self, hop): diff --git a/rpython/memory/gctransform/test/test_framework.py b/rpython/memory/gctransform/test/test_framework.py --- a/rpython/memory/gctransform/test/test_framework.py +++ b/rpython/memory/gctransform/test/test_framework.py @@ -1,6 +1,6 @@ from rpython.annotator.listdef import s_list_of_strings from rpython.annotator.model import SomeInteger -from rpython.flowspace.model import Constant, SpaceOperation +from rpython.flowspace.model import Constant, SpaceOperation, mkentrymap from rpython.rtyper.lltypesystem import lltype, rffi from rpython.rtyper.lltypesystem.lloperation import llop from rpython.memory.gc.semispace import SemiSpaceGC @@ -231,6 +231,33 @@ Constant('b', lltype.Void), varoftype(PTR_TYPE2)], varoftype(lltype.Void))) +def test_remove_duplicate_write_barrier(): + from rpython.translator.c.genc import CStandaloneBuilder + from rpython.flowspace.model import summary + + class A(object): + pass + glob_a_1 = A() + glob_a_2 = A() + + def f(a, cond): + a.x = a + a.z = a + if cond: + a.y = a + def g(): + f(glob_a_1, 5) + f(glob_a_2, 0) + t = rtype(g, []) + t.config.translation.gc = "minimark" + cbuild = CStandaloneBuilder(t, g, t.config, + gcpolicy=FrameworkGcPolicy2) + db = cbuild.generate_graphs_for_llinterp() + + ff = graphof(t, f) + #ff.show() + assert summary(ff)['direct_call'] == 1 # only one remember_young_pointer + def test_find_initializing_stores(): class A(object): @@ -246,7 +273,8 @@ etrafo = ExceptionTransformer(t) graphs = etrafo.transform_completely() collect_analyzer = CollectAnalyzer(t) - init_stores = find_initializing_stores(collect_analyzer, t.graphs[0]) + init_stores = find_initializing_stores(collect_analyzer, t.graphs[0], + mkentrymap(t.graphs[0])) assert len(init_stores) == 1 def test_find_initializing_stores_across_blocks(): @@ -271,7 +299,8 @@ etrafo = ExceptionTransformer(t) graphs = etrafo.transform_completely() collect_analyzer = CollectAnalyzer(t) - init_stores = find_initializing_stores(collect_analyzer, t.graphs[0]) + init_stores = find_initializing_stores(collect_analyzer, t.graphs[0], + mkentrymap(t.graphs[0])) assert len(init_stores) == 5 def test_find_clean_setarrayitems(): diff --git a/rpython/memory/gctransform/transform.py b/rpython/memory/gctransform/transform.py --- a/rpython/memory/gctransform/transform.py +++ b/rpython/memory/gctransform/transform.py @@ -83,6 +83,7 @@ class BaseGCTransformer(object): finished_helpers = False + curr_block = None def __init__(self, translator, inline=False): self.translator = translator @@ -159,7 +160,7 @@ def transform_block(self, block, is_borrowed): llops = LowLevelOpList() - #self.curr_block = block + 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)] @@ -205,6 +206,7 @@ block.operations[:] = llops self.livevars = None self.var_last_needed_in = None + self.curr_block = None def transform_graph(self, graph): if graph in self.minimal_transform: diff --git a/rpython/translator/c/genc.py b/rpython/translator/c/genc.py --- a/rpython/translator/c/genc.py +++ b/rpython/translator/c/genc.py @@ -485,7 +485,7 @@ else: mk.definition('DEBUGFLAGS', '-O1 -g') if self.translator.platform.name == 'msvc': - mk.rule('debug_target', 'debugmode_$(DEFAULT_TARGET)', 'rem') + mk.rule('debug_target', '$(DEFAULT_TARGET)', 'rem') else: mk.rule('debug_target', '$(DEFAULT_TARGET)', '#') mk.write() _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit