[pypy-commit] pypy default: merge
fijal
noreply at buildbot.pypy.org
Mon Jun 29 11:17:05 CEST 2015
Author: Maciej Fijalkowski <fijall at 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()
More information about the pypy-commit
mailing list