[pypy-commit] pypy default: make TranslatorDriver.from_targetspec a classmethod

2016-05-09 Thread william_ml_leslie
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

2016-05-09 Thread arigo
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

2016-05-09 Thread arigo
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

2016-05-09 Thread arigo
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

2016-05-09 Thread arigo
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

2016-05-09 Thread plan_rich
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)

2016-05-09 Thread arigo
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

2016-05-09 Thread arigo
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

2016-05-09 Thread arigo
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

2016-05-09 Thread arigo
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

2016-05-09 Thread arigo
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

2016-05-09 Thread arigo
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

2016-05-09 Thread plan_rich
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

2016-05-09 Thread plan_rich
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

2016-05-09 Thread arigo
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

2016-05-09 Thread arigo
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

2016-05-09 Thread arigo
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

2016-05-09 Thread plan_rich
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)

2016-05-09 Thread plan_rich
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

2016-05-09 Thread arigo
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'

2016-05-09 Thread william_ml_leslie
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

2016-05-09 Thread william_ml_leslie
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

2016-05-09 Thread mattip
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).

2016-05-09 Thread devin.jeanpierre
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

2016-05-09 Thread pjenvey
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

2016-05-09 Thread pjenvey
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