[pypy-commit] pypy default: make TranslatorDriver.from_targetspec a classmethod
Author: William ML Leslie Branch: Changeset: r84318:6ffd3556369a Date: 2016-05-09 16:59 +1000 http://bitbucket.org/pypy/pypy/changeset/6ffd3556369a/ Log:make TranslatorDriver.from_targetspec a classmethod diff --git a/rpython/translator/driver.py b/rpython/translator/driver.py --- a/rpython/translator/driver.py +++ b/rpython/translator/driver.py @@ -552,16 +552,16 @@ self.log.info('usession directory: %s' % (udir,)) return result -@staticmethod -def from_targetspec(targetspec_dic, config=None, args=None, +@classmethod +def from_targetspec(cls, targetspec_dic, config=None, args=None, empty_translator=None, disable=[], default_goal=None): if args is None: args = [] -driver = TranslationDriver(config=config, default_goal=default_goal, - disable=disable) +driver = cls(config=config, default_goal=default_goal, + disable=disable) target = targetspec_dic['target'] spec = target(driver, args) ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy default: A test (passing on -A). Its failure could be related to the next lxml
Author: Armin Rigo Branch: Changeset: r84319:ad7a580821ea Date: 2016-05-09 09:21 +0200 http://bitbucket.org/pypy/pypy/changeset/ad7a580821ea/ Log:A test (passing on -A). Its failure could be related to the next lxml crash. diff --git a/pypy/module/cpyext/test/test_typeobject.py b/pypy/module/cpyext/test/test_typeobject.py --- a/pypy/module/cpyext/test/test_typeobject.py +++ b/pypy/module/cpyext/test/test_typeobject.py @@ -921,3 +921,57 @@ 'multiple bases have instance lay-out conflict') else: raise AssertionError("did not get TypeError!") + +def test_call_tp_dealloc_when_created_from_python(self): +import gc +module = self.import_extension('foo', [ +("fetchFooType", "METH_VARARGS", + """ +PyObject *o; +Foo_Type.tp_dealloc = &dealloc_foo; +Foo_Type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE; +Foo_Type.tp_new = &new_foo; +Foo_Type.tp_free = &PyObject_Del; +if (PyType_Ready(&Foo_Type) < 0) return NULL; + +o = PyObject_New(PyObject, &Foo_Type); +Py_DECREF(o); /* calls dealloc_foo immediately */ + +Py_INCREF(&Foo_Type); +return (PyObject *)&Foo_Type; + """), +("getCounter", "METH_VARARGS", + """ +return PyInt_FromLong(foo_dealloc_counter); + """)], prologue= +""" +static int foo_dealloc_counter = -1; +static void dealloc_foo(PyObject *foo) { +foo_dealloc_counter++; +} +static PyObject *new_foo(PyTypeObject *t, PyObject *a, PyObject *k) +{ +return t->tp_alloc(t, 0); +} +static PyTypeObject Foo_Type = { +PyVarObject_HEAD_INIT(NULL, 0) +"foo.foo", +}; +""") +Foo = module.fetchFooType() +assert module.getCounter() == 0 +Foo(); Foo() +for i in range(10): +if module.getCounter() >= 2: +break +gc.collect() +assert module.getCounter() == 2 +# +class Bar(Foo): +pass +Bar(); Bar() +for i in range(10): +if module.getCounter() >= 4: +break +gc.collect() +assert module.getCounter() == 4 ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy default: Use an xfail, to be nice
Author: Armin Rigo Branch: Changeset: r84320:93c3da9adab4 Date: 2016-05-09 09:23 +0200 http://bitbucket.org/pypy/pypy/changeset/93c3da9adab4/ Log:Use an xfail, to be nice diff --git a/pypy/module/cpyext/test/test_typeobject.py b/pypy/module/cpyext/test/test_typeobject.py --- a/pypy/module/cpyext/test/test_typeobject.py +++ b/pypy/module/cpyext/test/test_typeobject.py @@ -922,6 +922,7 @@ else: raise AssertionError("did not get TypeError!") +@pytest.mark.xfail def test_call_tp_dealloc_when_created_from_python(self): import gc module = self.import_extension('foo', [ ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy default: Fix the test. Now it fails only for subclasses, which is what I
Author: Armin Rigo Branch: Changeset: r84321:4e12001044f0 Date: 2016-05-09 09:30 +0200 http://bitbucket.org/pypy/pypy/changeset/4e12001044f0/ Log:Fix the test. Now it fails only for subclasses, which is what I originally expected diff --git a/pypy/module/cpyext/test/test_typeobject.py b/pypy/module/cpyext/test/test_typeobject.py --- a/pypy/module/cpyext/test/test_typeobject.py +++ b/pypy/module/cpyext/test/test_typeobject.py @@ -924,7 +924,6 @@ @pytest.mark.xfail def test_call_tp_dealloc_when_created_from_python(self): -import gc module = self.import_extension('foo', [ ("fetchFooType", "METH_VARARGS", """ @@ -965,7 +964,9 @@ for i in range(10): if module.getCounter() >= 2: break -gc.collect() +# NB. use self.debug_collect() instead of gc.collect(), +# otherwise rawrefcount's dealloc callback doesn't trigger +self.debug_collect() assert module.getCounter() == 2 # class Bar(Foo): @@ -974,5 +975,5 @@ for i in range(10): if module.getCounter() >= 4: break -gc.collect() +self.debug_collect() assert module.getCounter() == 4 ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy default: Fix for 4e12001044f0
Author: Armin Rigo Branch: Changeset: r84322:979d7c8fcf6b Date: 2016-05-09 10:04 +0200 http://bitbucket.org/pypy/pypy/changeset/979d7c8fcf6b/ Log:Fix for 4e12001044f0 diff --git a/pypy/module/cpyext/test/test_typeobject.py b/pypy/module/cpyext/test/test_typeobject.py --- a/pypy/module/cpyext/test/test_typeobject.py +++ b/pypy/module/cpyext/test/test_typeobject.py @@ -922,7 +922,6 @@ else: raise AssertionError("did not get TypeError!") -@pytest.mark.xfail def test_call_tp_dealloc_when_created_from_python(self): module = self.import_extension('foo', [ ("fetchFooType", "METH_VARARGS", @@ -942,15 +941,16 @@ """), ("getCounter", "METH_VARARGS", """ -return PyInt_FromLong(foo_dealloc_counter); +return PyInt_FromLong(foo_counter); """)], prologue= """ -static int foo_dealloc_counter = -1; +static int foo_counter = 1000; static void dealloc_foo(PyObject *foo) { -foo_dealloc_counter++; +foo_counter += 10; } static PyObject *new_foo(PyTypeObject *t, PyObject *a, PyObject *k) { +foo_counter += 1000; return t->tp_alloc(t, 0); } static PyTypeObject Foo_Type = { @@ -959,21 +959,21 @@ }; """) Foo = module.fetchFooType() -assert module.getCounter() == 0 +assert module.getCounter() == 1010 Foo(); Foo() for i in range(10): -if module.getCounter() >= 2: +if module.getCounter() >= 3030: break # NB. use self.debug_collect() instead of gc.collect(), # otherwise rawrefcount's dealloc callback doesn't trigger self.debug_collect() -assert module.getCounter() == 2 +assert module.getCounter() == 3030 # class Bar(Foo): pass Bar(); Bar() for i in range(10): -if module.getCounter() >= 4: +if module.getCounter() >= 5050: break self.debug_collect() -assert module.getCounter() == 4 +assert module.getCounter() == 5050 diff --git a/pypy/module/cpyext/typeobject.py b/pypy/module/cpyext/typeobject.py --- a/pypy/module/cpyext/typeobject.py +++ b/pypy/module/cpyext/typeobject.py @@ -556,7 +556,14 @@ typedescr = get_typedescr(w_type.layout.typedef) # dealloc -pto.c_tp_dealloc = typedescr.get_dealloc(space) +if space.gettypeobject(w_type.layout.typedef) is w_type: +# only for the exact type, like 'space.w_tuple' or 'space.w_list' +pto.c_tp_dealloc = typedescr.get_dealloc(space) +else: +# for all subtypes, use subtype_dealloc() +pto.c_tp_dealloc = llhelper( +subtype_dealloc.api_func.functype, +subtype_dealloc.api_func.get_wrapper(space)) # buffer protocol if space.is_w(w_type, space.w_str): setup_string_buffer_procs(space, pto) ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] buildbot default: moved py3k 1h later (at 4 o'clock) and running py3.5 nightlies at 3 o'clock
Author: Richard Plangger Branch: Changeset: r1003:60db764e3567 Date: 2016-05-09 10:03 +0200 http://bitbucket.org/pypy/buildbot/changeset/60db764e3567/ Log:moved py3k 1h later (at 4 o'clock) and running py3.5 nightlies at 3 o'clock diff --git a/bot2/pypybuildbot/master.py b/bot2/pypybuildbot/master.py --- a/bot2/pypybuildbot/master.py +++ b/bot2/pypybuildbot/master.py @@ -304,10 +304,13 @@ NUMPY_WIN, # on allegro_win32, SalsaSalsa ]), +Nightly("nightly-3-01-py3.5", [LINUX64, JITLINUX64,], +branch="py3.5", hour=3, minute=0), + Nightly("nightly-3-00-py3k", [ LINUX64, # on bencher4, uses all cores JITLINUX64,# on bencher4, uses 1 core -], branch="py3k", hour=3, minute=0), +], branch="py3k", hour=4, minute=0), # S390X vm (ibm-research) Nightly("nightly-4-00", [LINUX_S390X], branch='default', hour=0, minute=0), ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy use-gc-del-3: Documentation (thanks cfbolz)
Author: Armin Rigo Branch: use-gc-del-3 Changeset: r84323:837ed78ee722 Date: 2016-05-09 10:28 +0200 http://bitbucket.org/pypy/pypy/changeset/837ed78ee722/ Log:Documentation (thanks cfbolz) diff --git a/pypy/doc/discussion/finalizer-order.rst b/pypy/doc/discussion/finalizer-order.rst --- a/pypy/doc/discussion/finalizer-order.rst +++ b/pypy/doc/discussion/finalizer-order.rst @@ -33,26 +33,25 @@ it from a finalizer. A finalizer runs earlier, and in topological order; care must be taken that the object might still be reachable at this point if we're clever enough. A destructor on the other hand runs -last; nothing can be done with the object any more. +last; nothing can be done with the object any more, and the GC frees it +immediately. Destructors --- A destructor is an RPython ``__del__()`` method that is called directly -by the GC when there is no more reference to an object. Intended for -objects that just need to free a block of raw memory or close a file. +by the GC when it is about to free the memory. Intended for objects +that just need to free an extra block of raw memory. There are restrictions on the kind of code you can put in ``__del__()``, including all other functions called by it. These restrictions are -checked. In particular you cannot access fields containing GC objects; -and if you call an external C function, it must be a "safe" function -(e.g. not releasing the GIL; use ``releasegil=False`` in -``rffi.llexternal()``). +checked. In particular you cannot access fields containing GC objects. +Right now you can't call any external C function either. -If there are several objects with destructors that die during the same -GC cycle, they are called in a completely random order --- but that -should not matter because destructors cannot do much anyway. +Destructors are called precisely when the GC frees the memory of the +object. As long as the object exists (even in some finalizer queue or +anywhere), its destructor is not called. Register_finalizer diff --git a/pypy/interpreter/executioncontext.py b/pypy/interpreter/executioncontext.py --- a/pypy/interpreter/executioncontext.py +++ b/pypy/interpreter/executioncontext.py @@ -548,11 +548,15 @@ def gc_disabled(self, w_obj): # If we're running in 'gc.disable()' mode, record w_obj in the -# "call me later" list and return True. Use this function -# from _finalize_() methods that would call app-level some -# things that we consider shouldn't be called in gc.disable(). -# (The exact definition is of course a bit vague, but most -# importantly this includes all user-level __del__().) +# "call me later" list and return True. In normal mode, return +# False. Use this function from some _finalize_() methods: +# if a _finalize_() method would call some user-defined +# app-level function, like a weakref callback, then first do +# 'if gc.disabled(self): return'. Another attempt at +# calling _finalize_() will be made after 'gc.enable()'. +# (The exact rule for when to use gc_disabled() or not is a bit +# vague, but most importantly this includes all user-level +# __del__().) pdd = self.pending_with_disabled_del if pdd is None: return False ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy use-gc-del-3: hg merge default
Author: Armin Rigo Branch: use-gc-del-3 Changeset: r84324:7b8178ec0f5b Date: 2016-05-09 10:29 +0200 http://bitbucket.org/pypy/pypy/changeset/7b8178ec0f5b/ Log:hg merge default diff --git a/dotviewer/graphserver.py b/dotviewer/graphserver.py --- a/dotviewer/graphserver.py +++ b/dotviewer/graphserver.py @@ -143,6 +143,11 @@ if __name__ == '__main__': if len(sys.argv) != 2: +if len(sys.argv) == 1: +# start locally +import sshgraphserver +sshgraphserver.ssh_graph_server(['LOCAL']) +sys.exit(0) print >> sys.stderr, __doc__ sys.exit(2) if sys.argv[1] == '--stdio': diff --git a/dotviewer/sshgraphserver.py b/dotviewer/sshgraphserver.py --- a/dotviewer/sshgraphserver.py +++ b/dotviewer/sshgraphserver.py @@ -4,11 +4,14 @@ Usage: sshgraphserver.py hostname [more args for ssh...] +sshgraphserver.py LOCAL This logs in to 'hostname' by passing the arguments on the command-line to ssh. No further configuration is required: it works for all programs using the dotviewer library as long as they run on 'hostname' under the same username as the one sshgraphserver logs as. + +If 'hostname' is the string 'LOCAL', then it starts locally without ssh. """ import graphserver, socket, subprocess, random @@ -18,12 +21,19 @@ s1 = socket.socket() s1.bind(('127.0.0.1', socket.INADDR_ANY)) localhost, localport = s1.getsockname() -remoteport = random.randrange(1, 2) -# ^^^ and just hope there is no conflict -args = ['ssh', '-S', 'none', '-C', '-R%d:127.0.0.1:%d' % (remoteport, localport)] -args = args + sshargs + ['python -u -c "exec input()"'] -print ' '.join(args[:-1]) +if sshargs[0] != 'LOCAL': +remoteport = random.randrange(1, 2) +# ^^^ and just hope there is no conflict + +args = ['ssh', '-S', 'none', '-C', '-R%d:127.0.0.1:%d' % ( +remoteport, localport)] +args = args + sshargs + ['python -u -c "exec input()"'] +else: +remoteport = localport +args = ['python', '-u', '-c', 'exec input()'] + +print ' '.join(args) p = subprocess.Popen(args, bufsize=0, stdin=subprocess.PIPE, stdout=subprocess.PIPE) diff --git a/lib_pypy/cffi/api.py b/lib_pypy/cffi/api.py --- a/lib_pypy/cffi/api.py +++ b/lib_pypy/cffi/api.py @@ -397,20 +397,7 @@ data. Later, when this new cdata object is garbage-collected, 'destructor(old_cdata_object)' will be called. """ -try: -gcp = self._backend.gcp -except AttributeError: -pass -else: -return gcp(cdata, destructor) -# -with self._lock: -try: -gc_weakrefs = self.gc_weakrefs -except AttributeError: -from .gc_weakref import GcWeakrefs -gc_weakrefs = self.gc_weakrefs = GcWeakrefs(self) -return gc_weakrefs.build(cdata, destructor) +return self._backend.gcp(cdata, destructor) def _get_cached_btype(self, type): assert self._lock.acquire(False) is False diff --git a/lib_pypy/cffi/backend_ctypes.py b/lib_pypy/cffi/backend_ctypes.py --- a/lib_pypy/cffi/backend_ctypes.py +++ b/lib_pypy/cffi/backend_ctypes.py @@ -460,6 +460,11 @@ return x._value raise TypeError("character expected, got %s" % type(x).__name__) +def __nonzero__(self): +return ord(self._value) != 0 +else: +def __nonzero__(self): +return self._value != 0 if kind == 'float': @staticmethod @@ -993,6 +998,31 @@ assert onerror is None # XXX not implemented return BType(source, error) +def gcp(self, cdata, destructor): +BType = self.typeof(cdata) + +if destructor is None: +if not (hasattr(BType, '_gcp_type') and +BType._gcp_type is BType): +raise TypeError("Can remove destructor only on a object " +"previously returned by ffi.gc()") +cdata._destructor = None +return None + +try: +gcp_type = BType._gcp_type +except AttributeError: +class CTypesDataGcp(BType): +__slots__ = ['_orig', '_destructor'] +def __del__(self): +if self._destructor is not None: +self._destructor(self._orig) +gcp_type = BType._gcp_type = CTypesDataGcp +new_cdata = self.cast(gcp_type, cdata) +new_cdata._orig = cdata +new_cdata._destructor = destructor +return new_cdata + typeof = type def getcname(self, BType, replace_with): diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head
[pypy-commit] pypy use-gc-del-3: branch doc
Author: Armin Rigo Branch: use-gc-del-3 Changeset: r84325:ca14ff0b53ba Date: 2016-05-09 10:38 +0200 http://bitbucket.org/pypy/pypy/changeset/ca14ff0b53ba/ Log:branch doc diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -84,3 +84,8 @@ .. branch: cpyext-more-slots +.. branch: use-gc-del-3 + +Use the new rgc.FinalizerQueue mechanism to clean up the handling of +``__del__`` methods. Fixes notably issue #2287. (All RPython +subclasses of W_Root need to use FinalizerQueue now.) ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy use-gc-del-3: ready to merge
Author: Armin Rigo Branch: use-gc-del-3 Changeset: r84326:0a4682d01440 Date: 2016-05-09 10:38 +0200 http://bitbucket.org/pypy/pypy/changeset/0a4682d01440/ Log:ready to merge ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy default: hg merge use-gc-del-3
Author: Armin Rigo Branch: Changeset: r84327:c8b895fb3548 Date: 2016-05-09 10:39 +0200 http://bitbucket.org/pypy/pypy/changeset/c8b895fb3548/ Log:hg merge use-gc-del-3 Use the new rgc.FinalizerQueue mechanism to clean up the handling of ``__del__`` methods. Fixes notably issue #2287. (All RPython subclasses of W_Root need to use FinalizerQueue now.) diff too long, truncating to 2000 out of 2012 lines diff --git a/pypy/doc/discussion/finalizer-order.rst b/pypy/doc/discussion/finalizer-order.rst --- a/pypy/doc/discussion/finalizer-order.rst +++ b/pypy/doc/discussion/finalizer-order.rst @@ -33,26 +33,25 @@ it from a finalizer. A finalizer runs earlier, and in topological order; care must be taken that the object might still be reachable at this point if we're clever enough. A destructor on the other hand runs -last; nothing can be done with the object any more. +last; nothing can be done with the object any more, and the GC frees it +immediately. Destructors --- A destructor is an RPython ``__del__()`` method that is called directly -by the GC when there is no more reference to an object. Intended for -objects that just need to free a block of raw memory or close a file. +by the GC when it is about to free the memory. Intended for objects +that just need to free an extra block of raw memory. There are restrictions on the kind of code you can put in ``__del__()``, including all other functions called by it. These restrictions are -checked. In particular you cannot access fields containing GC objects; -and if you call an external C function, it must be a "safe" function -(e.g. not releasing the GIL; use ``releasegil=False`` in -``rffi.llexternal()``). +checked. In particular you cannot access fields containing GC objects. +Right now you can't call any external C function either. -If there are several objects with destructors that die during the same -GC cycle, they are called in a completely random order --- but that -should not matter because destructors cannot do much anyway. +Destructors are called precisely when the GC frees the memory of the +object. As long as the object exists (even in some finalizer queue or +anywhere), its destructor is not called. Register_finalizer @@ -95,10 +94,15 @@ To find the queued items, call ``fin.next_dead()`` repeatedly. It returns the next queued item, or ``None`` when the queue is empty. -It is allowed in theory to cumulate several different +In theory, it would kind of work if you cumulate several different ``FinalizerQueue`` instances for objects of the same class, and (always in theory) the same ``obj`` could be registered several times in the same queue, or in several queues. This is not tested though. +For now the untranslated emulation does not support registering the +same object several times. + +Note that the Boehm garbage collector, used in ``rpython -O0``, +completely ignores ``register_finalizer()``. Ordering of finalizers diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -84,3 +84,8 @@ .. branch: cpyext-more-slots +.. branch: use-gc-del-3 + +Use the new rgc.FinalizerQueue mechanism to clean up the handling of +``__del__`` methods. Fixes notably issue #2287. (All RPython +subclasses of W_Root need to use FinalizerQueue now.) diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py --- a/pypy/interpreter/baseobjspace.py +++ b/pypy/interpreter/baseobjspace.py @@ -11,7 +11,7 @@ INT_MIN, INT_MAX, UINT_MAX, USHRT_MAX from pypy.interpreter.executioncontext import (ExecutionContext, ActionFlag, -UserDelAction) +make_finalizer_queue) from pypy.interpreter.error import OperationError, new_exception_class, oefmt from pypy.interpreter.argument import Arguments from pypy.interpreter.miscutils import ThreadLocals, make_weak_value_dictionary @@ -28,6 +28,7 @@ """This is the abstract root class of all wrapped objects that live in a 'normal' object space like StdObjSpace.""" __slots__ = ('__weakref__',) +_must_be_light_finalizer_ = True user_overridden_class = False def getdict(self, space): @@ -136,9 +137,8 @@ pass def clear_all_weakrefs(self): -"""Call this at the beginning of interp-level __del__() methods -in subclasses. It ensures that weakrefs (if any) are cleared -before the object is further destroyed. +"""Ensures that weakrefs (if any) are cleared now. This is +called by UserDelAction before the object is finalized further. """ lifeline = self.getweakref() if lifeline is not None: @@ -151,25 +151,37 @@ self.delweakref() lifeline.clear_all_weakrefs() -__already_enqueued_for_destruction = () +def _finalize_(self): +"""The RPython-level finalizer. -def enqueue_for_destruction(self, spac
[pypy-commit] pypy default: For binary compatibility with PyPy 5.1
Author: Armin Rigo Branch: Changeset: r84328:c86b42dd7613 Date: 2016-05-09 10:53 +0200 http://bitbucket.org/pypy/pypy/changeset/c86b42dd7613/ Log:For binary compatibility with PyPy 5.1 diff --git a/pypy/module/cpyext/src/abstract.c b/pypy/module/cpyext/src/abstract.c --- a/pypy/module/cpyext/src/abstract.c +++ b/pypy/module/cpyext/src/abstract.c @@ -326,3 +326,9 @@ return tmp; } +/* for binary compatibility with 5.1 */ +PyAPI_FUNC(void) PyPyObject_Del(PyObject *); +void PyPyObject_Del(PyObject *op) +{ +PyObject_FREE(op); +} ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy new-jit-log: merged deafult
Author: Richard Plangger Branch: new-jit-log Changeset: r84329:d46d42219c06 Date: 2016-05-09 10:13 +0200 http://bitbucket.org/pypy/pypy/changeset/d46d42219c06/ Log:merged deafult diff too long, truncating to 2000 out of 39303 lines diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -20,3 +20,5 @@ 5f8302b8bf9f53056e40426f10c72151564e5b19 release-4.0.1 246c9cf22037b11dc0e8c29ce3f291d3b8c5935a release-5.0 bbd45126bc691f669c4ebdfbd74456cd274c6b92 release-5.0.1 +3260adbeba4a8b6659d1cc0d0b41f266769b74da release-5.1 +b0a649e90b6642251fb4a765fe5b27a97b1319a9 release-5.1.1 diff --git a/dotviewer/graphserver.py b/dotviewer/graphserver.py --- a/dotviewer/graphserver.py +++ b/dotviewer/graphserver.py @@ -143,6 +143,11 @@ if __name__ == '__main__': if len(sys.argv) != 2: +if len(sys.argv) == 1: +# start locally +import sshgraphserver +sshgraphserver.ssh_graph_server(['LOCAL']) +sys.exit(0) print >> sys.stderr, __doc__ sys.exit(2) if sys.argv[1] == '--stdio': diff --git a/dotviewer/sshgraphserver.py b/dotviewer/sshgraphserver.py --- a/dotviewer/sshgraphserver.py +++ b/dotviewer/sshgraphserver.py @@ -4,11 +4,14 @@ Usage: sshgraphserver.py hostname [more args for ssh...] +sshgraphserver.py LOCAL This logs in to 'hostname' by passing the arguments on the command-line to ssh. No further configuration is required: it works for all programs using the dotviewer library as long as they run on 'hostname' under the same username as the one sshgraphserver logs as. + +If 'hostname' is the string 'LOCAL', then it starts locally without ssh. """ import graphserver, socket, subprocess, random @@ -18,12 +21,19 @@ s1 = socket.socket() s1.bind(('127.0.0.1', socket.INADDR_ANY)) localhost, localport = s1.getsockname() -remoteport = random.randrange(1, 2) -# ^^^ and just hope there is no conflict -args = ['ssh', '-S', 'none', '-C', '-R%d:127.0.0.1:%d' % (remoteport, localport)] -args = args + sshargs + ['python -u -c "exec input()"'] -print ' '.join(args[:-1]) +if sshargs[0] != 'LOCAL': +remoteport = random.randrange(1, 2) +# ^^^ and just hope there is no conflict + +args = ['ssh', '-S', 'none', '-C', '-R%d:127.0.0.1:%d' % ( +remoteport, localport)] +args = args + sshargs + ['python -u -c "exec input()"'] +else: +remoteport = localport +args = ['python', '-u', '-c', 'exec input()'] + +print ' '.join(args) p = subprocess.Popen(args, bufsize=0, stdin=subprocess.PIPE, stdout=subprocess.PIPE) diff --git a/lib-python/2.7/distutils/cmd.py b/lib-python/2.7/distutils/cmd.py --- a/lib-python/2.7/distutils/cmd.py +++ b/lib-python/2.7/distutils/cmd.py @@ -298,8 +298,16 @@ src_cmd_obj.ensure_finalized() for (src_option, dst_option) in option_pairs: if getattr(self, dst_option) is None: -setattr(self, dst_option, -getattr(src_cmd_obj, src_option)) +try: +setattr(self, dst_option, +getattr(src_cmd_obj, src_option)) +except AttributeError: +# This was added after problems with setuptools 18.4. +# It seems that setuptools 20.9 fixes the problem. +# But e.g. on Ubuntu 14.04 with /usr/bin/virtualenv +# if I say "virtualenv -p pypy venv-pypy" then it +# just installs setuptools 18.4 from some cache... +pass def get_finalized_command(self, command, create=1): diff --git a/lib-python/2.7/test/test_descr.py b/lib-python/2.7/test/test_descr.py --- a/lib-python/2.7/test/test_descr.py +++ b/lib-python/2.7/test/test_descr.py @@ -1735,7 +1735,6 @@ ("__reversed__", reversed, empty_seq, set(), {}), ("__length_hint__", list, zero, set(), {"__iter__" : iden, "next" : stop}), -("__sizeof__", sys.getsizeof, zero, set(), {}), ("__instancecheck__", do_isinstance, return_true, set(), {}), ("__missing__", do_dict_missing, some_number, set(("__class__",)), {}), @@ -1747,6 +1746,8 @@ ("__format__", format, format_impl, set(), {}), ("__dir__", dir, empty_seq, set(), {}), ] +if test_support.check_impl_detail(): +specials.append(("__sizeof__", sys.getsizeof, zero, set(), {})) class Checker(object): def __getattr__(self, attr, test=self): @@ -1768,10 +1769,6 @@ raise MyException for name, runner, meth_impl, ok, env in specials: -if name == '__length_hint__' or name == '__sizeof__': -if not test_support.check_impl_detail(): -continue -
[pypy-commit] pypy new-jit-log: moved the debug counter in its own file (debug.py). this was necessary to get a handle to the loop counters when calling jitlog_disable
Author: Richard Plangger Branch: new-jit-log Changeset: r84330:5f0da389d027 Date: 2016-05-09 11:44 +0200 http://bitbucket.org/pypy/pypy/changeset/5f0da389d027/ Log:moved the debug counter in its own file (debug.py). this was necessary to get a handle to the loop counters when calling jitlog_disable diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py --- a/rpython/jit/backend/arm/assembler.py +++ b/rpython/jit/backend/arm/assembler.py @@ -14,7 +14,7 @@ CoreRegisterManager, check_imm_arg, VFPRegisterManager, operations as regalloc_operations) from rpython.jit.backend.llsupport import jitframe, rewrite -from rpython.jit.backend.llsupport.assembler import DEBUG_COUNTER, BaseAssembler +from rpython.jit.backend.llsupport.assembler import BaseAssembler from rpython.jit.backend.llsupport.regalloc import get_scale, valid_addressing_size from rpython.jit.backend.llsupport.asmmemmgr import MachineDataBlockWrapper from rpython.jit.backend.model import CompiledLoopToken diff --git a/rpython/jit/backend/llsupport/assembler.py b/rpython/jit/backend/llsupport/assembler.py --- a/rpython/jit/backend/llsupport/assembler.py +++ b/rpython/jit/backend/llsupport/assembler.py @@ -13,13 +13,8 @@ from rpython.rtyper.annlowlevel import cast_instance_to_gcref, llhelper from rpython.rtyper.lltypesystem import rffi, lltype - -DEBUG_COUNTER = lltype.Struct('DEBUG_COUNTER', -# 'b'ridge, 'l'abel or # 'e'ntry point -('i', lltype.Signed), # first field, at offset 0 -('type', lltype.Char), -('number', lltype.Signed) -) +from rpython.jit.metainterp.debug import (DEBUG_COUNTER, LOOP_RUN_COUNTERS, +flush_debug_counters) class GuardToken(object): def __init__(self, cpu, gcmap, faildescr, failargs, fail_locs, @@ -362,10 +357,6 @@ ResOperation(rop.INCREMENT_DEBUG_COUNTER, [c_adr])) def _register_counter(self, tp, number, token): -# YYY very minor leak -- we need the counters to stay alive -# forever, just because we want to report them at the end -# of the process - # XXX the numbers here are ALMOST unique, but not quite, use a counter # or something struct = lltype.malloc(DEBUG_COUNTER, flavor='raw', @@ -377,14 +368,15 @@ else: assert token struct.number = compute_unique_id(token) -self.loop_run_counters.append(struct) +LOOP_RUN_COUNTERS.append(struct) return struct def finish_once(self, jitlog): if self._debug: +# TODO remove the old logging system when jitlog is complete debug_start('jit-backend-counts') -for i in range(len(self.loop_run_counters)): -struct = self.loop_run_counters[i] +for i in range(len(LOOP_RUN_COUNTERS)): +struct = LOOP_RUN_COUNTERS[i] if struct.type == 'l': prefix = 'TargetToken(%d)' % struct.number else: @@ -401,9 +393,7 @@ debug_stop('jit-backend-counts') if jitlog: -# this is always called, the jitlog knows if it is enabled -for i, struct in enumerate(self.loop_run_counters): -jitlog.log_jit_counter(struct) +flush_debug_counters(jitlog) @staticmethod @rgc.no_collect diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -3,8 +3,7 @@ import py from rpython.jit.backend.llsupport import symbolic, jitframe, rewrite -from rpython.jit.backend.llsupport.assembler import (GuardToken, BaseAssembler, -DEBUG_COUNTER, debug_bridge) +from rpython.jit.backend.llsupport.assembler import (GuardToken, BaseAssembler, debug_bridge) from rpython.jit.backend.llsupport.asmmemmgr import MachineDataBlockWrapper from rpython.jit.backend.llsupport.gcmap import allocate_gcmap from rpython.jit.metainterp.history import (Const, VOID, ConstInt) diff --git a/rpython/jit/metainterp/pyjitpl.py b/rpython/jit/metainterp/pyjitpl.py --- a/rpython/jit/metainterp/pyjitpl.py +++ b/rpython/jit/metainterp/pyjitpl.py @@ -1760,7 +1760,7 @@ self.cpu = cpu self.stats = self.cpu.stats self.options = options -self.jitlog = jl.VMProfJitLogger() +self.jitlog = jl.VMProfJitLogger(self.cpu) self.logger_noopt = Logger(self) self.logger_ops = Logger(self, guard_number=True) diff --git a/rpython/rlib/jitlog.py b/rpython/rlib/jitlog.py --- a/rpython/rlib/jitlog.py +++ b/rpython/rlib/jitlog.py @@ -222,8 +222,19 @@ content.append(encode_str(opname.lower())) return ''.join(content) + +def _log_jit_counter(cintf, struct): +if not cintf.jitlog_enabled(): +return +le_addr = encode_le_addr(struct.number) +# not an address (
[pypy-commit] pypy default: Found the next bug: when you have a Python subclass of a C API type, and
Author: Armin Rigo Branch: Changeset: r84332:adc30cc041ed Date: 2016-05-09 11:48 +0200 http://bitbucket.org/pypy/pypy/changeset/adc30cc041ed/ Log:Found the next bug: when you have a Python subclass of a C API type, and when you instantiate this Python subclass using C code (!), then tp_new is not called diff --git a/pypy/module/cpyext/test/test_typeobject.py b/pypy/module/cpyext/test/test_typeobject.py --- a/pypy/module/cpyext/test/test_typeobject.py +++ b/pypy/module/cpyext/test/test_typeobject.py @@ -942,6 +942,14 @@ Py_INCREF(&Foo_Type); return (PyObject *)&Foo_Type; """), +("newInstance", "METH_O", + """ +PyTypeObject *tp = (PyTypeObject *)args; +PyObject *e = PyTuple_New(0); +PyObject *o = tp->tp_new(tp, e, NULL); +Py_DECREF(e); +return o; + """), ("getCounter", "METH_VARARGS", """ return PyInt_FromLong(foo_counter); @@ -1000,3 +1008,17 @@ break self.debug_collect() assert module.getCounter() == 5050 +# +module.newInstance(Foo) +for i in range(10): +if module.getCounter() >= 6060: +break +self.debug_collect() +assert module.getCounter() == 6060 +# +module.newInstance(Bar) +for i in range(10): +if module.getCounter() >= 7070: +break +self.debug_collect() +#assert module.getCounter() == 7070-- oops, bug! ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy default: Extra tests, making very very sure that new_foo() is called
Author: Armin Rigo Branch: Changeset: r84331:b6f3b01b132c Date: 2016-05-09 11:40 +0200 http://bitbucket.org/pypy/pypy/changeset/b6f3b01b132c/ Log:Extra tests, making very very sure that new_foo() is called diff --git a/pypy/module/cpyext/test/test_typeobject.py b/pypy/module/cpyext/test/test_typeobject.py --- a/pypy/module/cpyext/test/test_typeobject.py +++ b/pypy/module/cpyext/test/test_typeobject.py @@ -927,13 +927,16 @@ ("fetchFooType", "METH_VARARGS", """ PyObject *o; +Foo_Type.tp_basicsize = sizeof(FooObject); Foo_Type.tp_dealloc = &dealloc_foo; -Foo_Type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_BASETYPE; +Foo_Type.tp_flags = Py_TPFLAGS_DEFAULT | Py_TPFLAGS_CHECKTYPES +| Py_TPFLAGS_BASETYPE; Foo_Type.tp_new = &new_foo; Foo_Type.tp_free = &PyObject_Del; if (PyType_Ready(&Foo_Type) < 0) return NULL; o = PyObject_New(PyObject, &Foo_Type); +init_foo(o); Py_DECREF(o); /* calls dealloc_foo immediately */ Py_INCREF(&Foo_Type); @@ -944,14 +947,34 @@ return PyInt_FromLong(foo_counter); """)], prologue= """ +typedef struct { +PyObject_HEAD +int someval[99]; +} FooObject; static int foo_counter = 1000; static void dealloc_foo(PyObject *foo) { +int i; foo_counter += 10; +for (i = 0; i < 99; i++) +if (((FooObject *)foo)->someval[i] != 1000 + i) +foo_counter += 10; /* error! */ +Py_TYPE(foo)->tp_free(foo); +} +static void init_foo(PyObject *o) +{ +int i; +if (o->ob_type->tp_basicsize < sizeof(FooObject)) +abort(); +for (i = 0; i < 99; i++) +((FooObject *)o)->someval[i] = 1000 + i; } static PyObject *new_foo(PyTypeObject *t, PyObject *a, PyObject *k) { +PyObject *o; foo_counter += 1000; -return t->tp_alloc(t, 0); +o = t->tp_alloc(t, 0); +init_foo(o); +return o; } static PyTypeObject Foo_Type = { PyVarObject_HEAD_INIT(NULL, 0) ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy default: Next fix
Author: Armin Rigo Branch: Changeset: r84333:e61e2f4a32fa Date: 2016-05-09 12:33 +0200 http://bitbucket.org/pypy/pypy/changeset/e61e2f4a32fa/ Log:Next fix diff --git a/pypy/module/cpyext/test/test_typeobject.py b/pypy/module/cpyext/test/test_typeobject.py --- a/pypy/module/cpyext/test/test_typeobject.py +++ b/pypy/module/cpyext/test/test_typeobject.py @@ -1002,6 +1002,7 @@ # class Bar(Foo): pass +assert Foo.__new__ is Bar.__new__ Bar(); Bar() for i in range(10): if module.getCounter() >= 5050: @@ -1021,4 +1022,4 @@ if module.getCounter() >= 7070: break self.debug_collect() -#assert module.getCounter() == 7070-- oops, bug! +assert module.getCounter() == 7070 diff --git a/pypy/module/cpyext/typeobject.py b/pypy/module/cpyext/typeobject.py --- a/pypy/module/cpyext/typeobject.py +++ b/pypy/module/cpyext/typeobject.py @@ -196,6 +196,10 @@ def update_all_slots(space, w_type, pto): # XXX fill slots in pto +# Not very sure about it, but according to +# test_call_tp_dealloc_when_created_from_python, we should not +# overwrite slots that are already set: these ones are probably +# coming from a parent C type. typedef = w_type.layout.typedef for method_name, slot_name, slot_names, slot_func in slotdefs_for_tp_slots: @@ -223,7 +227,8 @@ # XXX special case wrapper-functions and use a "specific" slot func if len(slot_names) == 1: -setattr(pto, slot_names[0], slot_func_helper) +if not getattr(pto, slot_names[0]): +setattr(pto, slot_names[0], slot_func_helper) else: assert len(slot_names) == 2 struct = getattr(pto, slot_names[0]) @@ -240,7 +245,8 @@ struct = lltype.malloc(STRUCT_TYPE, flavor='raw', zero=True) setattr(pto, slot_names[0], struct) -setattr(struct, slot_names[1], slot_func_helper) +if not getattr(struct, slot_names[1]): +setattr(struct, slot_names[1], slot_func_helper) def add_operators(space, dict_w, pto): # XXX support PyObject_HashNotImplemented ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy new-jit-log: provided wrong argument to flush_debug_counters
Author: Richard Plangger Branch: new-jit-log Changeset: r84334:84716af5f182 Date: 2016-05-09 11:49 +0200 http://bitbucket.org/pypy/pypy/changeset/84716af5f182/ Log:provided wrong argument to flush_debug_counters diff --git a/rpython/jit/backend/llsupport/assembler.py b/rpython/jit/backend/llsupport/assembler.py --- a/rpython/jit/backend/llsupport/assembler.py +++ b/rpython/jit/backend/llsupport/assembler.py @@ -393,7 +393,7 @@ debug_stop('jit-backend-counts') if jitlog: -flush_debug_counters(jitlog) +flush_debug_counters(jitlog.cintf) @staticmethod @rgc.no_collect ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy new-jit-log: forgot file (thx armin)
Author: Richard Plangger Branch: new-jit-log Changeset: r84335:f60619823f3b Date: 2016-05-09 12:43 +0200 http://bitbucket.org/pypy/pypy/changeset/f60619823f3b/ Log:forgot file (thx armin) diff --git a/rpython/jit/metainterp/debug.py b/rpython/jit/metainterp/debug.py new file mode 100644 --- /dev/null +++ b/rpython/jit/metainterp/debug.py @@ -0,0 +1,27 @@ +from rpython.rtyper.lltypesystem import rffi, lltype +from rpython.rlib.jitlog import _log_jit_counter + +# YYY very minor leak -- we need the counters to stay alive +# forever, just because we want to report them at the end +# of the process + +LOOP_RUN_COUNTERS = [] + +DEBUG_COUNTER = lltype.Struct('DEBUG_COUNTER', +# 'b'ridge, 'l'abel or # 'e'ntry point +('i', lltype.Signed), # first field, at offset 0 +('type', lltype.Char), +('number', lltype.Signed) +) + +def flush_debug_counters(cintf): +# this is always called, the jitlog knows if it is enabled +for i in range(len(LOOP_RUN_COUNTERS)): +struct = LOOP_RUN_COUNTERS[i] +_log_jit_counter(cintf, struct) +# reset the counter, flush in a later point in time will +# add up the counters! +struct.i = 0 +# here would be the point to free some counters +# see YYY comment above! but first we should run this every once in a while +# not just when jitlog_disable is called ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy default: Blind fix for issue #2285: rare vmprof segfaults on OS/X
Author: Armin Rigo Branch: Changeset: r84336:57e12f1aa41b Date: 2016-05-09 14:04 +0200 http://bitbucket.org/pypy/pypy/changeset/57e12f1aa41b/ Log:Blind fix for issue #2285: rare vmprof segfaults on OS/X diff --git a/rpython/rlib/rvmprof/src/vmprof_common.h b/rpython/rlib/rvmprof/src/vmprof_common.h --- a/rpython/rlib/rvmprof/src/vmprof_common.h +++ b/rpython/rlib/rvmprof/src/vmprof_common.h @@ -82,6 +82,10 @@ int n = 0; intptr_t addr = 0; int bottom_jitted = 0; + +if (stack == NULL) +return 0; + // check if the pc is in JIT #ifdef PYPY_JIT_CODEMAP if (pypy_find_codemap_at_addr((intptr_t)pc, &addr)) { @@ -111,7 +115,12 @@ #ifndef RPYTHON_LL2CTYPES static vmprof_stack_t *get_vmprof_stack(void) { -return RPY_THREADLOCALREF_GET(vmprof_tl_stack); +struct pypy_threadlocal_s *tl; +_OP_THREADLOCALREF_ADDR_SIGHANDLER(tl); +if (tl == NULL) +return NULL; +else +return tl->vmprof_tl_stack; } #else static vmprof_stack_t *get_vmprof_stack(void) diff --git a/rpython/translator/c/src/threadlocal.h b/rpython/translator/c/src/threadlocal.h --- a/rpython/translator/c/src/threadlocal.h +++ b/rpython/translator/c/src/threadlocal.h @@ -53,6 +53,13 @@ r = _RPython_ThreadLocals_Build(); \ } while (0) +#define _OP_THREADLOCALREF_ADDR_SIGHANDLER(r) \ +do {\ +r = (char *)&pypy_threadlocal; \ +if (pypy_threadlocal.ready != 42) \ +r = NULL; \ +} while (0) + #define RPY_THREADLOCALREF_ENSURE() \ if (pypy_threadlocal.ready != 42) \ (void)_RPython_ThreadLocals_Build(); @@ -87,6 +94,11 @@ r = _RPython_ThreadLocals_Build(); \ } while (0) +#define _OP_THREADLOCALREF_ADDR_SIGHANDLER(r) \ +do {\ +r = (char *)_RPy_ThreadLocals_Get();\ +} while (0) + #define RPY_THREADLOCALREF_ENSURE() \ if (!_RPy_ThreadLocals_Get()) \ (void)_RPython_ThreadLocals_Build(); ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy taskengine-sorted-optionals: Optional dependencies should take part in ordering even if they become non-optional 'later'
Author: William ML Leslie Branch: taskengine-sorted-optionals Changeset: r84337:cb82010dadbc Date: 2016-05-10 02:02 +1000 http://bitbucket.org/pypy/pypy/changeset/cb82010dadbc/ Log:Optional dependencies should take part in ordering even if they become non-optional 'later' diff --git a/rpython/translator/tool/taskengine.py b/rpython/translator/tool/taskengine.py --- a/rpython/translator/tool/taskengine.py +++ b/rpython/translator/tool/taskengine.py @@ -13,7 +13,7 @@ tasks[task_name] = task, task_deps -def _plan(self, goals, skip=[]): +def _plan(self, goals, skip=()): skip = [toskip for toskip in skip if toskip not in goals] key = (tuple(goals), tuple(skip)) @@ -21,64 +21,46 @@ return self._plan_cache[key] except KeyError: pass -constraints = [] - -def subgoals(task_name): -taskcallable, deps = self.tasks[task_name] -for dep in deps: -if dep.startswith('??'): # optional -dep = dep[2:] -if dep not in goals: -continue -if dep.startswith('?'): # suggested -dep = dep[1:] -if dep in skip: -continue -yield dep - -seen = {} - -def consider(subgoal): -if subgoal in seen: -return -else: -seen[subgoal] = True -constraints.append([subgoal]) -deps = subgoals(subgoal) -for dep in deps: -constraints.append([subgoal, dep]) -consider(dep) - -for goal in goals: -consider(goal) - -#sort plan = [] +goal_walker = goals[::-1] +flattened_goals = [] +for base_goal in goals[::-1]: +goal_walker = [base_goal] +dep_walker = [iter(self.tasks[base_goal.lstrip('?')][1])] +while goal_walker: +for subgoal in dep_walker[-1]: +break +else: +# all dependencies are in flattened_goals. record +# this goal. +dep_walker.pop() +goal = goal_walker.pop() +if goal not in flattened_goals: +flattened_goals.append(goal) +continue +if subgoal in goal_walker: +raise RuntimeException('circular dependency') -while True: -cands = dict.fromkeys([constr[0] for constr in constraints if constr]) -if not cands: -break +# subgoal must be at least as optional as its parent +qs = goal_walker[-1].count('?') +if subgoal.count('?') < qs: +subgoal = '?' * qs + subgoal.lstrip('?') -for cand in cands: -for constr in constraints: -if cand in constr[1:]: -break -else: -break -else: -raise RuntimeError("circular dependecy") +# we'll add this goal once we have its dependencies. +goal_walker.append(subgoal) +dep_walker.append(iter(self.tasks[subgoal.lstrip('?')][1])) -plan.append(cand) -for constr in constraints: -if constr and constr[0] == cand: -del constr[0] - -plan.reverse() - +plan = [] +for name in flattened_goals: +name = name.lstrip('?') +if name in plan: +continue +will_run = name in flattened_goals or ( +'?' + name in flattened_goals and name not in skip) +if will_run: +plan.append(name) self._plan_cache[key] = plan - return plan def _depending_on(self, goal): diff --git a/rpython/translator/tool/test/test_taskengine.py b/rpython/translator/tool/test/test_taskengine.py --- a/rpython/translator/tool/test/test_taskengine.py +++ b/rpython/translator/tool/test/test_taskengine.py @@ -148,3 +148,29 @@ assert drv._plan(['D', 'T', 'R']) == ['A', 'R', 'b', 'H', 'T', 'B', 'D'] assert drv._plan(['D', 'T']) == ['A', 'R', 'b', 'H', 'T', 'B', 'D'] assert drv._plan(['D', 'T'], skip=['B']) == ['A', 'R', 'b', 'H', 'T', 'D'] + + +def test_can_be_optional(): +class Drv(SimpleTaskEngine): +def task_A(): +pass + +def task_B(): +pass + +task_B.task_deps = ['??A'] + +def task_C(): +pass + +task_C.task_deps = ['??B'] + +def task_D(): +pass + +task_D.task_deps = ['B', 'C'] + +drv = Drv() +assert drv._plan(['D']) == ['B', 'C', 'D'] +assert drv._plan(['B', 'D']) == ['B', 'C', 'D
[pypy-commit] pypy taskengine-sorted-optionals: Use toposort + lattice
Author: William ML Leslie Branch: taskengine-sorted-optionals Changeset: r84338:76a012472eda Date: 2016-05-10 03:08 +1000 http://bitbucket.org/pypy/pypy/changeset/76a012472eda/ Log:Use toposort + lattice diff --git a/rpython/translator/tool/taskengine.py b/rpython/translator/tool/taskengine.py --- a/rpython/translator/tool/taskengine.py +++ b/rpython/translator/tool/taskengine.py @@ -22,44 +22,57 @@ except KeyError: pass -plan = [] -goal_walker = goals[::-1] -flattened_goals = [] -for base_goal in goals[::-1]: -goal_walker = [base_goal] -dep_walker = [iter(self.tasks[base_goal.lstrip('?')][1])] -while goal_walker: -for subgoal in dep_walker[-1]: -break -else: -# all dependencies are in flattened_goals. record -# this goal. -dep_walker.pop() -goal = goal_walker.pop() -if goal not in flattened_goals: -flattened_goals.append(goal) -continue -if subgoal in goal_walker: -raise RuntimeException('circular dependency') +optionality = dict((goal.lstrip('?'), goal.count('?')) + for goal in goals) +task_deps = {} -# subgoal must be at least as optional as its parent -qs = goal_walker[-1].count('?') -if subgoal.count('?') < qs: -subgoal = '?' * qs + subgoal.lstrip('?') +def will_do(task): +priority = optionality[task] +if priority < 1: +return True +return priority == 1 and task not in skip -# we'll add this goal once we have its dependencies. -goal_walker.append(subgoal) -dep_walker.append(iter(self.tasks[subgoal.lstrip('?')][1])) +goal_walker = list(goals[::-1]) +while goal_walker: +goal = goal_walker.pop() +qs = optionality.get(goal, 0) +if goal not in task_deps: +task_deps[goal] = deps = set() +for dep in self.tasks[goal][1]: +deps.add(dep.lstrip('?')) +for dep in self.tasks[goal][1]: +depname = dep.lstrip('?') +def_optionality = optionality.get(depname, 5) +dep_qs = max(qs, dep.count('?')) +if dep_qs < def_optionality: +optionality[depname] = dep_qs +goal_walker.append(depname) + +for task, deps in list(task_deps.iteritems()): +if not will_do(task): +del task_deps[task] +else: +if task in deps: +deps.remove(task) +for dep in list(deps): +if not will_do(dep): +deps.remove(dep) plan = [] -for name in flattened_goals: -name = name.lstrip('?') -if name in plan: -continue -will_run = name in flattened_goals or ( -'?' + name in flattened_goals and name not in skip) -if will_run: -plan.append(name) +seen = set() +tasks = list(task_deps) +while tasks: +remaining = [] +for task in tasks: +if task_deps[task] - seen: +remaining.append(task) +else: +plan.append(task) +seen.add(task) +if len(remaining) == len(tasks): +raise RuntimeException('circular dependency') +tasks = remaining + self._plan_cache[key] = plan return plan ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy cpyext-macros-cast: merge default into branch
Author: Matti Picus Branch: cpyext-macros-cast Changeset: r84339:664e7d4392f4 Date: 2016-05-09 21:42 +0300 http://bitbucket.org/pypy/pypy/changeset/664e7d4392f4/ Log:merge default into branch diff too long, truncating to 2000 out of 3197 lines diff --git a/lib_pypy/cffi/api.py b/lib_pypy/cffi/api.py --- a/lib_pypy/cffi/api.py +++ b/lib_pypy/cffi/api.py @@ -397,20 +397,7 @@ data. Later, when this new cdata object is garbage-collected, 'destructor(old_cdata_object)' will be called. """ -try: -gcp = self._backend.gcp -except AttributeError: -pass -else: -return gcp(cdata, destructor) -# -with self._lock: -try: -gc_weakrefs = self.gc_weakrefs -except AttributeError: -from .gc_weakref import GcWeakrefs -gc_weakrefs = self.gc_weakrefs = GcWeakrefs(self) -return gc_weakrefs.build(cdata, destructor) +return self._backend.gcp(cdata, destructor) def _get_cached_btype(self, type): assert self._lock.acquire(False) is False diff --git a/lib_pypy/cffi/backend_ctypes.py b/lib_pypy/cffi/backend_ctypes.py --- a/lib_pypy/cffi/backend_ctypes.py +++ b/lib_pypy/cffi/backend_ctypes.py @@ -460,6 +460,11 @@ return x._value raise TypeError("character expected, got %s" % type(x).__name__) +def __nonzero__(self): +return ord(self._value) != 0 +else: +def __nonzero__(self): +return self._value != 0 if kind == 'float': @staticmethod @@ -993,6 +998,31 @@ assert onerror is None # XXX not implemented return BType(source, error) +def gcp(self, cdata, destructor): +BType = self.typeof(cdata) + +if destructor is None: +if not (hasattr(BType, '_gcp_type') and +BType._gcp_type is BType): +raise TypeError("Can remove destructor only on a object " +"previously returned by ffi.gc()") +cdata._destructor = None +return None + +try: +gcp_type = BType._gcp_type +except AttributeError: +class CTypesDataGcp(BType): +__slots__ = ['_orig', '_destructor'] +def __del__(self): +if self._destructor is not None: +self._destructor(self._orig) +gcp_type = BType._gcp_type = CTypesDataGcp +new_cdata = self.cast(gcp_type, cdata) +new_cdata._orig = cdata +new_cdata._destructor = destructor +return new_cdata + typeof = type def getcname(self, BType, replace_with): diff --git a/pypy/doc/discussion/finalizer-order.rst b/pypy/doc/discussion/finalizer-order.rst --- a/pypy/doc/discussion/finalizer-order.rst +++ b/pypy/doc/discussion/finalizer-order.rst @@ -33,26 +33,25 @@ it from a finalizer. A finalizer runs earlier, and in topological order; care must be taken that the object might still be reachable at this point if we're clever enough. A destructor on the other hand runs -last; nothing can be done with the object any more. +last; nothing can be done with the object any more, and the GC frees it +immediately. Destructors --- A destructor is an RPython ``__del__()`` method that is called directly -by the GC when there is no more reference to an object. Intended for -objects that just need to free a block of raw memory or close a file. +by the GC when it is about to free the memory. Intended for objects +that just need to free an extra block of raw memory. There are restrictions on the kind of code you can put in ``__del__()``, including all other functions called by it. These restrictions are -checked. In particular you cannot access fields containing GC objects; -and if you call an external C function, it must be a "safe" function -(e.g. not releasing the GIL; use ``releasegil=False`` in -``rffi.llexternal()``). +checked. In particular you cannot access fields containing GC objects. +Right now you can't call any external C function either. -If there are several objects with destructors that die during the same -GC cycle, they are called in a completely random order --- but that -should not matter because destructors cannot do much anyway. +Destructors are called precisely when the GC frees the memory of the +object. As long as the object exists (even in some finalizer queue or +anywhere), its destructor is not called. Register_finalizer @@ -95,10 +94,15 @@ To find the queued items, call ``fin.next_dead()`` repeatedly. It returns the next queued item, or ``None`` when the queue is empty. -It is allowed in theory to cumulate several different +In theory, it would kind of work if you cumulate several di
[pypy-commit] pypy cpyext-macros-cast: Remove trailing semicolons on macros (yikes).
Author: Devin Jeanpierre Branch: cpyext-macros-cast Changeset: r84340:cbcd8db8ebf5 Date: 2016-05-09 13:01 -0700 http://bitbucket.org/pypy/pypy/changeset/cbcd8db8ebf5/ Log:Remove trailing semicolons on macros (yikes). diff --git a/pypy/module/cpyext/include/intobject.h b/pypy/module/cpyext/include/intobject.h --- a/pypy/module/cpyext/include/intobject.h +++ b/pypy/module/cpyext/include/intobject.h @@ -7,7 +7,7 @@ extern "C" { #endif -#define PyInt_AS_LONG(obj) _PyInt_AS_LONG((PyObject*)obj); +#define PyInt_AS_LONG(obj) _PyInt_AS_LONG((PyObject*)obj) typedef struct { PyObject_HEAD diff --git a/pypy/module/cpyext/include/setobject.h b/pypy/module/cpyext/include/setobject.h --- a/pypy/module/cpyext/include/setobject.h +++ b/pypy/module/cpyext/include/setobject.h @@ -6,7 +6,7 @@ extern "C" { #endif -#define PySet_GET_SIZE(obj) _PySet_GET_SIZE((PyObject*)obj); +#define PySet_GET_SIZE(obj) _PySet_GET_SIZE((PyObject*)obj) #ifdef __cplusplus } ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3k: adapt to py3k
Author: Philip Jenvey Branch: py3k Changeset: r84341:bc87e9e3fa04 Date: 2016-05-09 15:03 -0700 http://bitbucket.org/pypy/pypy/changeset/bc87e9e3fa04/ Log:adapt to py3k diff --git a/lib_pypy/resource.py b/lib_pypy/resource.py --- a/lib_pypy/resource.py +++ b/lib_pypy/resource.py @@ -104,7 +104,7 @@ all_constants = [] p = lib.my_rlimit_consts while p.name: -name = ffi.string(p.name) +name = ffi.string(p.name).decode() globals()[name] = int(p.value) all_constants.append(name) p += 1 ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3k: reapply xfails from default
Author: Philip Jenvey Branch: py3k Changeset: r84342:c871cbd337d4 Date: 2016-05-09 18:54 -0700 http://bitbucket.org/pypy/pypy/changeset/c871cbd337d4/ Log:reapply xfails from default diff --git a/lib-python/3/ctypes/test/test_python_api.py b/lib-python/3/ctypes/test/test_python_api.py --- a/lib-python/3/ctypes/test/test_python_api.py +++ b/lib-python/3/ctypes/test/test_python_api.py @@ -19,6 +19,7 @@ class PythonAPITestCase(unittest.TestCase): +@xfail def test_PyBytes_FromStringAndSize(self): PyBytes_FromStringAndSize = pythonapi.PyBytes_FromStringAndSize @@ -71,6 +72,7 @@ del pyobj self.assertEqual(grc(s), ref) +@xfail def test_PyOS_snprintf(self): PyOS_snprintf = pythonapi.PyOS_snprintf PyOS_snprintf.argtypes = POINTER(c_char), c_size_t, c_char_p @@ -85,6 +87,7 @@ # not enough arguments self.assertRaises(TypeError, PyOS_snprintf, buf) +@xfail def test_pyobject_repr(self): self.assertEqual(repr(py_object()), "py_object()") self.assertEqual(repr(py_object(42)), "py_object(42)") ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit