[pypy-commit] pypy memory-accounting: add tracking of memory
Author: fijal Branch: memory-accounting Changeset: r93011:5e198814c5f6 Date: 2017-11-14 10:19 +0100 http://bitbucket.org/pypy/pypy/changeset/5e198814c5f6/ Log:add tracking of memory diff --git a/pypy/module/gc/__init__.py b/pypy/module/gc/__init__.py --- a/pypy/module/gc/__init__.py +++ b/pypy/module/gc/__init__.py @@ -19,6 +19,7 @@ space.config.translation.gctransformer == "framework"): self.appleveldefs.update({ 'dump_rpy_heap': 'app_referents.dump_rpy_heap', +'get_stats': 'app_referents.get_stats', }) self.interpleveldefs.update({ 'get_rpy_roots': 'referents.get_rpy_roots', @@ -28,7 +29,7 @@ 'get_objects': 'referents.get_objects', 'get_referents': 'referents.get_referents', 'get_referrers': 'referents.get_referrers', -'get_stats': 'referents.get_stats', +'_get_stats': 'referents.get_stats', '_dump_rpy_heap': 'referents._dump_rpy_heap', 'get_typeids_z': 'referents.get_typeids_z', 'get_typeids_list': 'referents.get_typeids_list', diff --git a/pypy/module/gc/app_referents.py b/pypy/module/gc/app_referents.py --- a/pypy/module/gc/app_referents.py +++ b/pypy/module/gc/app_referents.py @@ -48,3 +48,42 @@ file.flush() fd = file.fileno() gc._dump_rpy_heap(fd) + +class GcStats(object): +def __init__(self, s): +self._s = s +for item in ('total_gc_memory', 'jit_backend_used', 'total_memory_pressure', + 'total_allocated_memory', 'jit_backend_allocated'): +setattr(self, item, self._format(getattr(self._s, item))) +self.memory_used_sum = self._format(self._s.total_gc_memory + self._s.total_memory_pressure + +self._s.jit_backend_used) +self.memory_allocated_sum = self._format(self._s.total_allocated_memory + self._s.total_memory_pressure + +self._s.jit_backend_allocated) + +def _format(self, v): +if v < 100: +# bit unlikely ;-) +return "%.1fkB" % (v / 1024.) +return "%.1fMB" % (v / 1024. / 1024.) + +def repr(self): +return """Total memory consumed: +GC used:%s +raw assembler used: %s +memory pressure:%s +- +Total: %s + +Total memory allocated: +GC allocated:%s +raw assembler allocated: %s +memory pressure: %s +- +Total: %s +""" % (self.total_gc_memory, self.jit_backend_used, self.total_memory_pressure, + self.memory_used_sum, + self.total_allocated_memory, self.jit_backend_allocated, self.total_memory_pressure, + self.memory_allocated_sum) + +def get_stats(): +return GcStats(gc._get_stats()) diff --git a/pypy/module/gc/referents.py b/pypy/module/gc/referents.py --- a/pypy/module/gc/referents.py +++ b/pypy/module/gc/referents.py @@ -1,7 +1,7 @@ -from rpython.rlib import rgc +from rpython.rlib import rgc, jit_hooks from pypy.interpreter.baseobjspace import W_Root from pypy.interpreter.typedef import TypeDef, interp_attrproperty -from pypy.interpreter.gateway import unwrap_spec +from pypy.interpreter.gateway import unwrap_spec, interp2app from pypy.interpreter.error import oefmt, wrap_oserror from rpython.rlib.objectmodel import we_are_translated @@ -175,12 +175,21 @@ def __init__(self): self.total_memory_pressure = rgc.get_stats(rgc.TOTAL_MEMORY_PRESSURE) self.total_gc_memory = rgc.get_stats(rgc.TOTAL_MEMORY) +self.total_allocated_memory = rgc.get_stats(rgc.TOTAL_ALLOCATED_MEMORY) +self.jit_backend_allocated = jit_hooks.stats_asmmemmgr_allocated(None) +self.jit_backend_used = jit_hooks.stats_asmmemmgr_used(None) W_GcStats.typedef = TypeDef("GcStats", total_memory_pressure=interp_attrproperty("total_memory_pressure", cls=W_GcStats, wrapfn="newint"), total_gc_memory=interp_attrproperty("total_gc_memory", -cls=W_GcStats, wrapfn="newint") +cls=W_GcStats, wrapfn="newint"), +total_allocated_memory=interp_attrproperty("total_allocated_memory", +cls=W_GcStats, wrapfn="newint"), +jit_backend_allocated=interp_attrproperty("jit_backend_allocated", +cls=W_GcStats, wrapfn="newint"), +jit_backend_used=interp_attrproperty("jit_backend_used", +cls=W_GcStats, wrapfn="newint"), ) def get_stats(space): diff --git a/rpython/memory/gc/incminimark.py b/rpython/memory/gc/incminimark.py --- a/rpython/memory/gc/incminimark.py +++ b/rpython/memory/gc/incminimark.py @@ -1184,6 +1184,11 @@ """ return self.ac.total_memory_used + self.rawmalloced_total_size +def get_total_memory_alloced(self): +""" Return the total memory allocated +""" +
[pypy-commit] pypy math-improvements: Don't return a copy on long // 1
Author: stian Branch: math-improvements Changeset: r93012:9838b9ca2938 Date: 2017-11-14 11:18 +0100 http://bitbucket.org/pypy/pypy/changeset/9838b9ca2938/ Log:Don't return a copy on long // 1 diff --git a/rpython/rlib/rbigint.py b/rpython/rlib/rbigint.py --- a/rpython/rlib/rbigint.py +++ b/rpython/rlib/rbigint.py @@ -788,8 +788,8 @@ if self.sign == 1 and other.numdigits() == 1 and other.sign == 1: digit = other.digit(0) if digit == 1: -return rbigint(self._digits[:self.numdigits()], 1, self.numdigits()) -elif digit and digit & (digit - 1) == 0: +return self +elif digit & (digit - 1) == 0: return self.rqshift(ptwotable[digit]) div, mod = _divrem(self, other) ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: backout b95f1240ad90: this was fixed in CPython 3.*
Author: Ronan Lamy Branch: py3.5 Changeset: r93013:714cdd09fc99 Date: 2017-11-14 16:03 + http://bitbucket.org/pypy/pypy/changeset/714cdd09fc99/ Log:backout b95f1240ad90: this was fixed in CPython 3.* diff --git a/pypy/interpreter/pyparser/future.py b/pypy/interpreter/pyparser/future.py --- a/pypy/interpreter/pyparser/future.py +++ b/pypy/interpreter/pyparser/future.py @@ -87,17 +87,13 @@ # permissive parsing of the given list of tokens; it relies on # the real parsing done afterwards to give errors. it.skip_newlines() +it.skip_name("r") or it.skip_name("u") or it.skip_name("ru") +if it.skip(pygram.tokens.STRING): +it.skip_newlines() -docstring_possible = True -while True: -it.skip_name("r") or it.skip_name("u") or it.skip_name("ru") -if docstring_possible and it.skip(pygram.tokens.STRING): -it.skip_newlines() -docstring_possible = False -if not (it.skip_name("from") and +while (it.skip_name("from") and it.skip_name("__future__") and it.skip_name("import")): -break it.skip(pygram.tokens.LPAR)# optionally # return in 'last_position' any line-column pair that points # somewhere inside the last __future__ import statement diff --git a/pypy/interpreter/pyparser/test/test_future.py b/pypy/interpreter/pyparser/test/test_future.py --- a/pypy/interpreter/pyparser/test/test_future.py +++ b/pypy/interpreter/pyparser/test/test_future.py @@ -193,13 +193,3 @@ 'from __future__ import with_statement;') f = run(s, (2, 23)) assert f == 0 - -def test_future_doc_future(): -# for some reason people do this :-[ -s = ''' -from __future__ import generators -"Docstring" -from __future__ import division -''' -f = run(s, (4, 24)) -assert f == 0 ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: Allow inspect._signature_from_callable() to work on builtins (by handling them like user functions)
Author: Ronan Lamy Branch: py3.5 Changeset: r93014:5d5dfbb116aa Date: 2017-11-14 16:31 + http://bitbucket.org/pypy/pypy/changeset/5d5dfbb116aa/ Log:Allow inspect._signature_from_callable() to work on builtins (by handling them like user functions) diff --git a/lib-python/3/inspect.py b/lib-python/3/inspect.py --- a/lib-python/3/inspect.py +++ b/lib-python/3/inspect.py @@ -1828,7 +1828,7 @@ kwdefaults = getattr(obj, '__kwdefaults__', _void) # ... and not None here annotations = getattr(obj, '__annotations__', None) -return (isinstance(code, types.CodeType) and +return (isinstance(code, (types.CodeType, _builtin_code_type)) and isinstance(name, str) and (defaults is None or isinstance(defaults, tuple)) and (kwdefaults is None or isinstance(kwdefaults, dict)) and ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: update test for PyPy
Author: Ronan Lamy Branch: py3.5 Changeset: r93015:b05acdc71ad8 Date: 2017-11-14 16:40 + http://bitbucket.org/pypy/pypy/changeset/b05acdc71ad8/ Log:update test for PyPy diff --git a/lib-python/3/test/test_inspect.py b/lib-python/3/test/test_inspect.py --- a/lib-python/3/test/test_inspect.py +++ b/lib-python/3/test/test_inspect.py @@ -816,7 +816,9 @@ attrs = attrs_wo_objs(A) -self.assertIn(('__new__', 'method', object), attrs, 'missing __new__') +# changed in PyPy +self.assertIn(('__new__', 'static method', object), attrs, 'missing __new__') + self.assertIn(('__init__', 'method', object), attrs, 'missing __init__') self.assertIn(('s', 'static method', A), attrs, 'missing static method') ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: Correctly compute .co_kwonlyargcount on BuiltinCode objects
Author: Ronan Lamy Branch: py3.5 Changeset: r93016:d129c0d2de48 Date: 2017-11-14 17:38 + http://bitbucket.org/pypy/pypy/changeset/d129c0d2de48/ Log:Correctly compute .co_kwonlyargcount on BuiltinCode objects diff --git a/pypy/interpreter/test/test_gateway.py b/pypy/interpreter/test/test_gateway.py --- a/pypy/interpreter/test/test_gateway.py +++ b/pypy/interpreter/test/test_gateway.py @@ -18,7 +18,7 @@ class TestBuiltinCode: -def test_signature(self): +def test_signature(self, space): def c(space, w_x, w_y, hello_w): pass code = gateway.BuiltinCode(c, unwrap_spec=[gateway.ObjSpace, @@ -53,6 +53,8 @@ code = gateway.BuiltinCode(f, unwrap_spec=[gateway.ObjSpace, "kwonly", W_Root]) assert code.signature() == Signature([], kwonlyargnames=['x']) +assert space.int_w(space.getattr( +code, space.newtext('co_kwonlyargcount'))) == 1 def test_call(self): diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py --- a/pypy/interpreter/typedef.py +++ b/pypy/interpreter/typedef.py @@ -538,6 +538,9 @@ def fget_co_argcount(space, code): # unwrapping through unwrap_spec return space.newint(code.signature().num_argnames()) +def fget_co_kwonlyargcount(space, code): # unwrapping through unwrap_spec +return space.newint(code.signature().num_kwonlyargnames()) + def fget_zero(space, code): return space.newint(0) @@ -597,7 +600,7 @@ co_name = interp_attrproperty('co_name', cls=BuiltinCode, wrapfn="newtext_or_none"), co_varnames = GetSetProperty(fget_co_varnames, cls=BuiltinCode), co_argcount = GetSetProperty(fget_co_argcount, cls=BuiltinCode), -co_kwonlyargcount = GetSetProperty(fget_zero, cls=BuiltinCode), +co_kwonlyargcount = GetSetProperty(fget_co_kwonlyargcount, cls=BuiltinCode), co_flags = GetSetProperty(fget_co_flags, cls=BuiltinCode), co_consts = GetSetProperty(fget_co_consts, cls=BuiltinCode), ) ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: ignoring test_finddoc seems acceptable
Author: Ronan Lamy Branch: py3.5 Changeset: r93017:f0a8cba78c24 Date: 2017-11-14 18:54 + http://bitbucket.org/pypy/pypy/changeset/f0a8cba78c24/ Log:ignoring test_finddoc seems acceptable diff --git a/lib-python/3/test/test_inspect.py b/lib-python/3/test/test_inspect.py --- a/lib-python/3/test/test_inspect.py +++ b/lib-python/3/test/test_inspect.py @@ -364,6 +364,7 @@ self.assertEqual(inspect.getdoc(mod.FesteringGob.contradiction), 'The automatic gainsaying.') +@cpython_only # XXX: _finddoc() is broken on PyPy, but getdoc() seems OK @unittest.skipIf(MISSING_C_DOCSTRINGS, "test requires docstrings") def test_finddoc(self): finddoc = inspect._finddoc ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: tweak test
Author: Ronan Lamy Branch: py3.5 Changeset: r93018:1465066182bd Date: 2017-11-14 19:01 + http://bitbucket.org/pypy/pypy/changeset/1465066182bd/ Log:tweak test diff --git a/lib-python/3/test/test_inspect.py b/lib-python/3/test/test_inspect.py --- a/lib-python/3/test/test_inspect.py +++ b/lib-python/3/test/test_inspect.py @@ -2023,7 +2023,7 @@ # This doesn't work now. # (We don't have a valid signature for "type" in 3.4) -with self.assertRaisesRegex(ValueError, "no signature found"): +with self.assertRaisesRegex(ValueError, "signature"): class ThisWorksNow: __call__ = type test_callable(ThisWorksNow()) ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: PyUnicode_FromObject only works on instances of str
Author: Ronan Lamy Branch: py3.5 Changeset: r93019:a3c86e99e3e4 Date: 2017-11-14 19:51 + http://bitbucket.org/pypy/pypy/changeset/a3c86e99e3e4/ Log:PyUnicode_FromObject only works on instances of str diff --git a/pypy/module/cpyext/test/test_unicodeobject.py b/pypy/module/cpyext/test/test_unicodeobject.py --- a/pypy/module/cpyext/test/test_unicodeobject.py +++ b/pypy/module/cpyext/test/test_unicodeobject.py @@ -319,6 +319,20 @@ assert module.unsafe_len(u'aАbБcСdД') == 8 assert module.unsafe_len(u"café\U0001F4A9") == 5 +def test_FromObject(self): +module = self.import_extension('foo', [ +("from_object", "METH_O", + """ +return PyUnicode_FromObject(args); + """)]) +class my_str(str): pass +assert module.from_object('abc') == 'abc' +res = module.from_object(my_str('abc')) +assert type(res) is str +assert res == 'abc' +raises(TypeError, module.from_object, b'abc') +raises(TypeError, module.from_object, 42) + class TestUnicode(BaseApiTest): def test_unicodeobject(self, space): @@ -500,6 +514,12 @@ assert ret == Py_CLEANUP_SUPPORTED assert space.isinstance_w(from_ref(space, result[0]), space.w_bytes) assert PyUnicode_FSDecoder(space, None, result) == 1 +# Input is invalid +w_input = space.newint(42) +with lltype.scoped_alloc(PyObjectP.TO, 1) as result: +with pytest.raises(OperationError): +PyUnicode_FSConverter(space, w_input, result) + def test_IS(self, space): for char in [0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x1c, 0x1d, 0x1e, 0x1f, diff --git a/pypy/module/cpyext/unicodeobject.py b/pypy/module/cpyext/unicodeobject.py --- a/pypy/module/cpyext/unicodeobject.py +++ b/pypy/module/cpyext/unicodeobject.py @@ -505,12 +505,19 @@ @cpython_api([PyObject], PyObject) def PyUnicode_FromObject(space, w_obj): -"""Shortcut for PyUnicode_FromEncodedObject(obj, NULL, "strict") which is used -throughout the interpreter whenever coercion to Unicode is needed.""" +"""Copy an instance of a Unicode subtype to a new true Unicode object if +necessary. If obj is already a true Unicode object (not a subtype), return +the reference with incremented refcount. + +Objects other than Unicode or its subtypes will cause a TypeError. +""" if space.is_w(space.type(w_obj), space.w_unicode): return w_obj +elif space.isinstance_w(w_obj, space.w_unicode): +return space.call_function(space.w_unicode, w_obj) else: -return space.call_function(space.w_unicode, w_obj) +raise oefmt(space.w_TypeError, +"Can't convert '%T' object to str implicitly", w_obj) @cpython_api([PyObject, CONST_STRING, CONST_STRING], PyObject) def PyUnicode_FromEncodedObject(space, w_obj, encoding, errors): ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: skip or tweak tests
Author: Ronan Lamy Branch: py3.5 Changeset: r93020:6f9bbe108de5 Date: 2017-11-14 20:12 + http://bitbucket.org/pypy/pypy/changeset/6f9bbe108de5/ Log:skip or tweak tests diff --git a/lib-python/3/test/test_capi.py b/lib-python/3/test/test_capi.py --- a/lib-python/3/test/test_capi.py +++ b/lib-python/3/test/test_capi.py @@ -53,6 +53,8 @@ self.assertEqual(testfunction.attribute, "test") self.assertRaises(AttributeError, setattr, inst.testfunction, "attribute", "test") +@unittest.skipIf(support.check_impl_detail(pypy=True), +"doesn't crash on PyPy") @unittest.skipUnless(threading, 'Threading required for this test.') def test_no_FatalError_infinite_loop(self): with support.SuppressCrashReport(): @@ -205,9 +207,9 @@ else: with self.assertRaises(SystemError) as cm: _testcapi.return_null_without_error() +# PyPy change: different message self.assertRegex(str(cm.exception), - 'return_null_without_error.* ' - 'returned NULL without setting an error') +'Function returned a NULL result without setting an exception') def test_return_result_with_error(self): # Issue #23571: A function must not return a result with an error set @@ -237,9 +239,9 @@ else: with self.assertRaises(SystemError) as cm: _testcapi.return_result_with_error() +# PyPy change: different message self.assertRegex(str(cm.exception), - 'return_result_with_error.* ' - 'returned a result with an error set') +'An exception was set, but function returned a value') def test_buildvalue_N(self): _testcapi.test_buildvalue_N() @@ -327,6 +329,8 @@ self.pendingcalls_wait(l, n) +@unittest.skipIf(support.check_impl_detail(pypy=True), +"subinterpreters not implemented on PyPy") class SubinterpreterTest(unittest.TestCase): def test_subinterps(self): ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: Unskip _testcapi tests that should pass, skip those that cannot
Author: Ronan Lamy Branch: py3.5 Changeset: r93021:66f524561285 Date: 2017-11-14 20:59 + http://bitbucket.org/pypy/pypy/changeset/66f524561285/ Log:Unskip _testcapi tests that should pass, skip those that cannot diff --git a/lib-python/3/test/test_capi.py b/lib-python/3/test/test_capi.py --- a/lib-python/3/test/test_capi.py +++ b/lib-python/3/test/test_capi.py @@ -29,8 +29,9 @@ skips = [] if support.check_impl_detail(pypy=True): skips += [ -'test_widechar', -] +'test_lazy_hash_inheritance', +'test_capsule', +] def testfunction(self): """some doc""" diff --git a/lib_pypy/_testcapimodule.c b/lib_pypy/_testcapimodule.c --- a/lib_pypy/_testcapimodule.c +++ b/lib_pypy/_testcapimodule.c @@ -2818,8 +2818,6 @@ return PyMemoryView_FromBuffer(&info); } -#ifndef PYPY_VERSION - static PyObject * test_from_contiguous(PyObject* self, PyObject *noargs) { @@ -2869,7 +2867,6 @@ Py_RETURN_NONE; } -#endif /* PYPY_VERSION */ #if (defined(__linux__) || defined(__FreeBSD__)) && defined(__GNUC__) && !defined(PYPY_VERSION) extern PyTypeObject _PyBytesIOBuffer_Type; @@ -3907,9 +3904,7 @@ {"test_string_to_double", (PyCFunction)test_string_to_double, METH_NOARGS}, {"test_unicode_compare_with_ascii", (PyCFunction)test_unicode_compare_with_ascii, METH_NOARGS}, {"test_capsule", (PyCFunction)test_capsule, METH_NOARGS}, -#ifndef PYPY_VERSION {"test_from_contiguous", (PyCFunction)test_from_contiguous, METH_NOARGS}, -#endif #if (defined(__linux__) || defined(__FreeBSD__)) && defined(__GNUC__) && !defined(PYPY_VERSION) {"test_pep3118_obsolete_write_locks", (PyCFunction)test_pep3118_obsolete_write_locks, METH_NOARGS}, #endif ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: Check for NULL in PyMemoryView_FromBuffer
Author: Ronan Lamy Branch: py3.5 Changeset: r93022:57dc41aeb601 Date: 2017-11-14 21:14 + http://bitbucket.org/pypy/pypy/changeset/57dc41aeb601/ Log:Check for NULL in PyMemoryView_FromBuffer diff --git a/pypy/module/cpyext/memoryobject.py b/pypy/module/cpyext/memoryobject.py --- a/pypy/module/cpyext/memoryobject.py +++ b/pypy/module/cpyext/memoryobject.py @@ -201,6 +201,10 @@ The memoryview object then owns the buffer represented by view, which means you shouldn't try to call PyBuffer_Release() yourself: it will be done on deallocation of the memoryview object.""" +if not view.c_buf: +raise oefmt(space.w_ValueError, +"PyMemoryView_FromBuffer(): info->buf must not be NULL") + # XXX this should allocate a PyMemoryViewObject and # copy view into obj.c_view, without creating a new view.c_obj typedescr = get_typedescr(W_MemoryView.typedef) diff --git a/pypy/module/cpyext/test/test_memoryobject.py b/pypy/module/cpyext/test/test_memoryobject.py --- a/pypy/module/cpyext/test/test_memoryobject.py +++ b/pypy/module/cpyext/test/test_memoryobject.py @@ -255,3 +255,13 @@ """)]) mv = module.new() assert mv.tobytes() == b'hell' + +def test_FromBuffer_NULL(self): +module = self.import_extension('foo', [ +('new', 'METH_NOARGS', """ +Py_buffer info; +if (PyBuffer_FillInfo(&info, NULL, NULL, 1, 1, PyBUF_FULL_RO) < 0) +return NULL; +return PyMemoryView_FromBuffer(&info); + """)]) +raises(ValueError, module.new) ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: Define SIZEOF_WCHAR_T in pyconfig.h and copy CPython logic for the related Py_UNICODE_XXX defines
Author: Ronan Lamy Branch: py3.5 Changeset: r93023:69a07b055bdd Date: 2017-11-14 21:43 + http://bitbucket.org/pypy/pypy/changeset/69a07b055bdd/ Log:Define SIZEOF_WCHAR_T in pyconfig.h and copy CPython logic for the related Py_UNICODE_XXX defines diff --git a/pypy/module/cpyext/include/pyconfig.h b/pypy/module/cpyext/include/pyconfig.h --- a/pypy/module/cpyext/include/pyconfig.h +++ b/pypy/module/cpyext/include/pyconfig.h @@ -21,10 +21,9 @@ /* PyPy supposes Py_UNICODE == wchar_t */ #define HAVE_USABLE_WCHAR_T 1 #ifndef _WIN32 -#define Py_UNICODE_SIZE 4 -#define Py_UNICODE_WIDE +#define SIZEOF_WCHAR_T 4 #else -#define Py_UNICODE_SIZE 2 +#define SIZEOF_WCHAR_T 2 #endif #ifndef _WIN32 diff --git a/pypy/module/cpyext/include/unicodeobject.h b/pypy/module/cpyext/include/unicodeobject.h --- a/pypy/module/cpyext/include/unicodeobject.h +++ b/pypy/module/cpyext/include/unicodeobject.h @@ -1,6 +1,25 @@ #ifndef Py_UNICODEOBJECT_H #define Py_UNICODEOBJECT_H +#ifndef SIZEOF_WCHAR_T +#error Must define SIZEOF_WCHAR_T +#endif + +#define Py_UNICODE_SIZE SIZEOF_WCHAR_T + +/* If wchar_t can be used for UCS-4 storage, set Py_UNICODE_WIDE. + Otherwise, Unicode strings are stored as UCS-2 (with limited support + for UTF-16) */ + +#if Py_UNICODE_SIZE >= 4 +#define Py_UNICODE_WIDE +#endif + +/* Set these flags if the platform has "wchar.h" and the + wchar_t type is a 16-bit unsigned type */ +/* #define HAVE_WCHAR_H */ +/* #define HAVE_USABLE_WCHAR_T */ + #ifdef __cplusplus extern "C" { #endif diff --git a/pypy/module/cpyext/test/test_unicodeobject.py b/pypy/module/cpyext/test/test_unicodeobject.py --- a/pypy/module/cpyext/test/test_unicodeobject.py +++ b/pypy/module/cpyext/test/test_unicodeobject.py @@ -333,6 +333,29 @@ raises(TypeError, module.from_object, b'abc') raises(TypeError, module.from_object, 42) +def test_widechar(self): +module = self.import_extension('foo', [ +("make_wide", "METH_NOARGS", + """ +#if defined(SIZEOF_WCHAR_T) && (SIZEOF_WCHAR_T == 4) +const wchar_t wtext[2] = {(wchar_t)0x10ABCDu}; +size_t wtextlen = 1; +const wchar_t invalid[1] = {(wchar_t)0x11u}; +#else +const wchar_t wtext[3] = {(wchar_t)0xDBEAu, (wchar_t)0xDFCDu}; +size_t wtextlen = 2; +#endif +return PyUnicode_FromWideChar(wtext, wtextlen); + """), +("make_utf8", "METH_NOARGS", + """ +return PyUnicode_FromString("\\xf4\\x8a\\xaf\\x8d"); + """)]) +wide = module.make_wide() +utf8 = module.make_utf8() +print(repr(wide), repr(utf8)) +assert wide == utf8 + class TestUnicode(BaseApiTest): def test_unicodeobject(self, space): ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: fix
Author: Ronan Lamy Branch: py3.5 Changeset: r93024:bf4ed8da1af1 Date: 2017-11-14 23:09 + http://bitbucket.org/pypy/pypy/changeset/bf4ed8da1af1/ Log:fix diff --git a/pypy/module/cpyext/memoryobject.py b/pypy/module/cpyext/memoryobject.py --- a/pypy/module/cpyext/memoryobject.py +++ b/pypy/module/cpyext/memoryobject.py @@ -1,3 +1,4 @@ +from pypy.interpreter.error import oefmt from pypy.module.cpyext.api import ( cpython_api, CANNOT_FAIL, Py_MAX_FMT, Py_MAX_NDIMS, build_type_checkers, Py_ssize_tP, cts, parse_dir, bootstrap_function, Py_bufferP, slot_function) ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy py3.5: Update getargs.c to match CPython 3.5.4
Author: Ronan Lamy Branch: py3.5 Changeset: r93025:00710c6f69a6 Date: 2017-11-14 23:10 + http://bitbucket.org/pypy/pypy/changeset/00710c6f69a6/ Log:Update getargs.c to match CPython 3.5.4 diff --git a/pypy/module/cpyext/src/getargs.c b/pypy/module/cpyext/src/getargs.c --- a/pypy/module/cpyext/src/getargs.c +++ b/pypy/module/cpyext/src/getargs.c @@ -35,14 +35,16 @@ } freelistentry_t; typedef struct { + freelistentry_t *entries; int first_available; - freelistentry_t *entries; + int entries_malloced; } freelist_t; +#define STATIC_FREELIST_ENTRIES 8 /* Forward */ static int vgetargs1(PyObject *, const char *, va_list *, int); -static void seterror(int, const char *, int *, const char *, const char *); +static void seterror(Py_ssize_t, const char *, int *, const char *, const char *); static char *convertitem(PyObject *, const char **, va_list *, int, int *, char *, size_t, freelist_t *); static char *converttuple(PyObject *, const char **, va_list *, int, @@ -176,7 +178,8 @@ freelist->entries[index].item); } } -PyMem_FREE(freelist->entries); +if (freelist->entries_malloced) +PyMem_FREE(freelist->entries); return retval; } @@ -195,8 +198,13 @@ const char *formatsave = format; Py_ssize_t i, len; char *msg; -freelist_t freelist = {0, NULL}; int compat = flags & FLAG_COMPAT; +freelistentry_t static_entries[STATIC_FREELIST_ENTRIES]; +freelist_t freelist; + +freelist.entries = static_entries; +freelist.first_available = 0; +freelist.entries_malloced = 0; assert(compat || (args != (PyObject*)NULL)); flags = flags & ~FLAG_COMPAT; @@ -229,15 +237,15 @@ message = format; endfmt = 1; break; +case '|': +if (level == 0) +min = max; +break; default: if (level == 0) { -if (c == 'O') -max++; -else if (isalpha(Py_CHARMASK(c))) { +if (isalpha(Py_CHARMASK(c))) if (c != 'e') /* skip encoded */ max++; -} else if (c == '|') -min = max; } break; } @@ -251,30 +259,31 @@ format = formatsave; -freelist.entries = PyMem_NEW(freelistentry_t, max); -if (freelist.entries == NULL) { -PyErr_NoMemory(); -return 0; +if (max > STATIC_FREELIST_ENTRIES) { +freelist.entries = PyMem_NEW(freelistentry_t, max); +if (freelist.entries == NULL) { +PyErr_NoMemory(); +return 0; +} +freelist.entries_malloced = 1; } if (compat) { if (max == 0) { if (args == NULL) return 1; -PyOS_snprintf(msgbuf, sizeof(msgbuf), - "%.200s%s takes no arguments", - fname==NULL ? "function" : fname, - fname==NULL ? "" : "()"); -PyErr_SetString(PyExc_TypeError, msgbuf); +PyErr_Format(PyExc_TypeError, + "%.200s%s takes no arguments", + fname==NULL ? "function" : fname, + fname==NULL ? "" : "()"); return cleanreturn(0, &freelist); } else if (min == 1 && max == 1) { if (args == NULL) { -PyOS_snprintf(msgbuf, sizeof(msgbuf), - "%.200s%s takes at least one argument", - fname==NULL ? "function" : fname, - fname==NULL ? "" : "()"); -PyErr_SetString(PyExc_TypeError, msgbuf); +PyErr_Format(PyExc_TypeError, + "%.200s%s takes at least one argument", + fname==NULL ? "function" : fname, + fname==NULL ? "" : "()"); return cleanreturn(0, &freelist); } msg = convertitem(args, &format, p_va, flags, levels, @@ -300,20 +309,18 @@ len = PyTuple_GET_SIZE(args); if (len < min || max < len) { -if (message == NULL) { -PyOS_snprintf(msgbuf, sizeof(msgbuf), - "%.150s%s takes %s %d argument%s " - "(%ld given)", - fname==NULL ? "function" : fname, - fname==NULL ? "" : "()", - min==max ? "exactly" - : len < min ? "at least" : "at most", - len < min ? min : max, - (len < min ? min : max) == 1 ? "" : "s", - Py_SAFE_DOWNCAST(len, Py_ssize_t, long)); -message = msgbuf; -} -PyErr_SetString(PyExc_TypeError, message); +if (message == NULL) +
[pypy-commit] pypy continulet-no-frame-loop: introduce the concept of running/paused continulet, depending on bottomframe.f_backref; fix the post_switch() logic to build the f_back chain correctly; fi
Author: Antonio Cuni Branch: continulet-no-frame-loop Changeset: r93032:d5212118820d Date: 2017-11-15 02:11 +0100 http://bitbucket.org/pypy/pypy/changeset/d5212118820d/ Log:introduce the concept of running/paused continulet, depending on bottomframe.f_backref; fix the post_switch() logic to build the f_back chain correctly; finally fix test_f_back to check that we do NOT build cycles of frames diff --git a/pypy/module/_continuation/interp_continuation.py b/pypy/module/_continuation/interp_continuation.py --- a/pypy/module/_continuation/interp_continuation.py +++ b/pypy/module/_continuation/interp_continuation.py @@ -17,6 +17,8 @@ # states: # - not init'ed: self.sthread == None # - normal: self.sthread != None, not is_empty_handle(self.h) +# * running: self.bottomframe.f_backref is not vref_None +# * paused: self.bottomframe.f_backref is vref_None # - finished:self.sthread != None, is_empty_handle(self.h) def check_sthread(self): @@ -275,8 +277,7 @@ self.h, origin.h = origin.h, h # current = sthread.ec.topframeref -lo -g(' SWITCH ') +log(' SWITCH ') pstack(sthread.ec.topframeref, 'sthread.ec.topframeref') pstack(self, 'self') @@ -285,15 +286,20 @@ self.bottomframe.f_backref = origin.bottomframe.f_backref origin.bottomframe.f_backref = current else: -# antocuni sthread.ec.topframeref = self.topframeref self.topframeref = origin.topframeref +self.bottomframe.f_backref = origin.bottomframe.f_backref origin.topframeref = current +if origin.bottomframe.f_backref is jit.vref_None: +# paused ==> running: build the f_back link +origin.bottomframe.f_backref = current +else: +# running ==> paused: break the f_back link +origin.bottomframe.f_backref = jit.vref_None # log('swap') pstack(sthread.ec.topframeref, 'sthread.ec.topframeref') -pstack(self -, 'self') +pstack(self, 'self') log(' END SWITCH ') log() return get_result() diff --git a/pypy/module/_continuation/test/test_stacklet.py b/pypy/module/_continuation/test/test_stacklet.py --- a/pypy/module/_continuation/test/test_stacklet.py +++ b/pypy/module/_continuation/test/test_stacklet.py @@ -406,27 +406,27 @@ f = main(c) assert seen == [1, 2, 3, 4, 5, 6] -def test_f_back(self): +def test_f_back_complex(self): import sys from _continuation import continulet stack = self.stack # def bar(c): -assert stack() == ['bar', 'foo', 'test_f_back'] +assert stack() == ['bar', 'foo', 'test_f_back_complex'] c.switch(sys._getframe(0)) c.switch(sys._getframe(0).f_back) c.switch(sys._getframe(1)) # -assert stack() == ['bar', 'foo', 'main', 'test_f_back'] +assert stack() == ['bar', 'foo', 'main', 'test_f_back_complex'] c.switch(sys._getframe(1).f_back) # -assert stack() == ['bar', 'foo', 'main2', 'test_f_back'] +assert stack() == ['bar', 'foo', 'main2', 'test_f_back_complex'] assert sys._getframe(2) is f3_foo.f_back c.switch(sys._getframe(2)) def foo(c): bar(c) # -assert stack() == ['test_f_back'] +assert stack() == ['test_f_back_complex'] c = continulet(foo) f1_bar = c.switch() assert f1_bar.f_code.co_name == 'bar' @@ -439,16 +439,16 @@ def main(): f4_main = c.switch() assert f4_main.f_code.co_name == 'main' -assert f3_foo.f_back is f1_bar# not running, so a loop -assert stack() == ['main', 'test_f_back'] -assert stack(f1_bar) == ['bar', 'foo', '...'] +assert f3_foo.f_back is None# not running +assert stack() == ['main', 'test_f_back_complex'] +assert stack(f1_bar) == ['bar', 'foo'] # def main2(): f5_main2 = c.switch() assert f5_main2.f_code.co_name == 'main2' -assert f3_foo.f_back is f1_bar# not running, so a loop -assert stack() == ['main2', 'test_f_back'] -assert stack(f1_bar) == ['bar', 'foo', '...'] +assert f3_foo.f_back is None# not running +assert stack() == ['main2', 'test_f_back_complex'] +assert stack(f1_bar) == ['bar', 'foo'] # main() main2() ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy continulet-no-frame-loop: add a passing test to check that we stick the continulet stack at the right position of the f_back chain
Author: Antonio Cuni Branch: continulet-no-frame-loop Changeset: r93031:82b54bb1e271 Date: 2017-11-15 02:01 +0100 http://bitbucket.org/pypy/pypy/changeset/82b54bb1e271/ Log:add a passing test to check that we stick the continulet stack at the right position of the f_back chain diff --git a/pypy/module/_continuation/test/test_stacklet.py b/pypy/module/_continuation/test/test_stacklet.py --- a/pypy/module/_continuation/test/test_stacklet.py +++ b/pypy/module/_continuation/test/test_stacklet.py @@ -378,6 +378,34 @@ assert stack(f) == ['bar', 'foo'] c.switch() +def test_f_back_proper_chaining(self): +import sys +from _continuation import continulet +stack = self.stack +# +seen = [] +def bar(c): +seen.append(2) +assert stack() == ['bar', 'foo', 'test_f_back_proper_chaining'] +c.switch() +seen.append(5) +assert stack() == ['bar', 'foo', 'main', + 'test_f_back_proper_chaining'] +def foo(c): +bar(c) +def main(c): +seen.append(4) +assert stack() == ['main', 'test_f_back_proper_chaining'] +c.switch() +seen.append(6) + +c = continulet(foo) +seen.append(1) +c.switch() +seen.append(3) +f = main(c) +assert seen == [1, 2, 3, 4, 5, 6] + def test_f_back(self): import sys from _continuation import continulet ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy default: merge heads
Author: Antonio Cuni Branch: Changeset: r93033:821e59360f37 Date: 2017-11-15 02:13 +0100 http://bitbucket.org/pypy/pypy/changeset/821e59360f37/ Log:merge heads diff --git a/pypy/module/_continuation/test/test_stacklet.py b/pypy/module/_continuation/test/test_stacklet.py --- a/pypy/module/_continuation/test/test_stacklet.py +++ b/pypy/module/_continuation/test/test_stacklet.py @@ -340,16 +340,41 @@ import sys from _continuation import continulet # +def stack(f=None): +""" +get the call-stack of the caller or the specified frame +""" +if f is None: +f = sys._getframe(1) +res = [] +seen = set() +while f: +if f in seen: +# frame loop +res.append('...') +break +seen.add(f) +res.append(f.f_code.co_name) +f = f.f_back +#print res +return res + def bar(c): +assert stack() == ['bar', 'foo', 'test_f_back'] c.switch(sys._getframe(0)) c.switch(sys._getframe(0).f_back) c.switch(sys._getframe(1)) +# +assert stack() == ['bar', 'foo', 'main', 'test_f_back'] c.switch(sys._getframe(1).f_back) +# +assert stack() == ['bar', 'foo', 'main2', 'test_f_back'] assert sys._getframe(2) is f3_foo.f_back c.switch(sys._getframe(2)) def foo(c): bar(c) # +assert stack() == ['test_f_back'] c = continulet(foo) f1_bar = c.switch() assert f1_bar.f_code.co_name == 'bar' @@ -358,14 +383,20 @@ f3_foo = c.switch() assert f3_foo is f2_foo assert f1_bar.f_back is f3_foo +# def main(): f4_main = c.switch() assert f4_main.f_code.co_name == 'main' assert f3_foo.f_back is f1_bar# not running, so a loop +assert stack() == ['main', 'test_f_back'] +assert stack(f1_bar) == ['bar', 'foo', '...'] +# def main2(): f5_main2 = c.switch() assert f5_main2.f_code.co_name == 'main2' assert f3_foo.f_back is f1_bar# not running, so a loop +assert stack(f1_bar) == ['bar', 'foo', '...'] +# main() main2() res = c.switch() ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy continulet-no-frame-loop: WIP: refactor test_xxx into a proper failing tests, with a decent name and real asserts
Author: Antonio Cuni Branch: continulet-no-frame-loop Changeset: r93030:3e4c6ca55d1d Date: 2017-11-15 01:54 +0100 http://bitbucket.org/pypy/pypy/changeset/3e4c6ca55d1d/ Log:WIP: refactor test_xxx into a proper failing tests, with a decent name and real asserts diff --git a/pypy/module/_continuation/test/test_stacklet.py b/pypy/module/_continuation/test/test_stacklet.py --- a/pypy/module/_continuation/test/test_stacklet.py +++ b/pypy/module/_continuation/test/test_stacklet.py @@ -8,6 +8,28 @@ cls.w_translated = cls.space.wrap( os.path.join(os.path.dirname(__file__), 'test_translated.py')) +cls.w_stack = cls.space.appexec([], """(): +import sys +def stack(f=None): +''' +get the call-stack of the caller or the specified frame +''' +if f is None: +f = sys._getframe(1) +res = [] +seen = set() +while f: +if f in seen: +# frame cycle (shouldn't happen) +res.append('...') +break +seen.add(f) +res.append(f.f_code.co_name) +f = f.f_back +#print res +return res +return stack + """) def test_new_empty(self): from _continuation import continulet @@ -336,70 +358,31 @@ assert res == 2002 assert seen == [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13] -def test_xxx(self): +def test_f_back_no_cycles(self): import sys from _continuation import continulet +stack = self.stack # -def stack(f=None): -""" -get the call-stack of the caller or the specified frame -""" -if f is None: -f = sys._getframe(1) -res = [] -seen = set() -while f: -if f in seen: -# frame loop -res.append('...') -break -seen.add(f) -res.append(f.f_code.co_name) -f = f.f_back -print res -return res - def bar(c): f = sys._getframe(0) -print 'bar 1' +assert stack() == ['bar', 'foo', 'test_f_back_no_cycles'] c.switch(f) -print 'bar 2' +assert stack() == ['bar', 'foo', 'test_f_back_no_cycles'] def foo(c): bar(c) - -print +# c = continulet(foo) -print 'test 1' +assert stack() == ['test_f_back_no_cycles'] f = c.switch() -print 'test 2' -xxx = c.switch() -print 'xxx', xxx -#stack() -#stack(f) +assert stack() == ['test_f_back_no_cycles'] +assert stack(f) == ['bar', 'foo'] +c.switch() def test_f_back(self): import sys from _continuation import continulet +stack = self.stack # -def stack(f=None): -""" -get the call-stack of the caller or the specified frame -""" -if f is None: -f = sys._getframe(1) -res = [] -seen = set() -while f: -if f in seen: -# frame loop -res.append('...') -break -seen.add(f) -res.append(f.f_code.co_name) -f = f.f_back -#print res -return res - def bar(c): assert stack() == ['bar', 'foo', 'test_f_back'] c.switch(sys._getframe(0)) @@ -436,6 +419,7 @@ f5_main2 = c.switch() assert f5_main2.f_code.co_name == 'main2' assert f3_foo.f_back is f1_bar# not running, so a loop +assert stack() == ['main2', 'test_f_back'] assert stack(f1_bar) == ['bar', 'foo', '...'] # main() ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy default: improve the test by also checking the full call-stack at various points. Probably it does not test anything more than before, but it is a good aid when you read it
Author: Antonio Cuni Branch: Changeset: r93027:b7758cca88a3 Date: 2017-11-13 18:40 +0100 http://bitbucket.org/pypy/pypy/changeset/b7758cca88a3/ Log:improve the test by also checking the full call-stack at various points. Probably it does not test anything more than before, but it is a good aid when you read it diff --git a/pypy/module/_continuation/test/test_stacklet.py b/pypy/module/_continuation/test/test_stacklet.py --- a/pypy/module/_continuation/test/test_stacklet.py +++ b/pypy/module/_continuation/test/test_stacklet.py @@ -340,16 +340,41 @@ import sys from _continuation import continulet # +def stack(f=None): +""" +get the call-stack of the caller or the specified frame +""" +if f is None: +f = sys._getframe(1) +res = [] +seen = set() +while f: +if f in seen: +# frame loop +res.append('...') +break +seen.add(f) +res.append(f.f_code.co_name) +f = f.f_back +#print res +return res + def bar(c): +assert stack() == ['bar', 'foo', 'test_f_back'] c.switch(sys._getframe(0)) c.switch(sys._getframe(0).f_back) c.switch(sys._getframe(1)) +# +assert stack() == ['bar', 'foo', 'main', 'test_f_back'] c.switch(sys._getframe(1).f_back) +# +assert stack() == ['bar', 'foo', 'main2', 'test_f_back'] assert sys._getframe(2) is f3_foo.f_back c.switch(sys._getframe(2)) def foo(c): bar(c) # +assert stack() == ['test_f_back'] c = continulet(foo) f1_bar = c.switch() assert f1_bar.f_code.co_name == 'bar' @@ -358,14 +383,20 @@ f3_foo = c.switch() assert f3_foo is f2_foo assert f1_bar.f_back is f3_foo +# def main(): f4_main = c.switch() assert f4_main.f_code.co_name == 'main' assert f3_foo.f_back is f1_bar# not running, so a loop +assert stack() == ['main', 'test_f_back'] +assert stack(f1_bar) == ['bar', 'foo', '...'] +# def main2(): f5_main2 = c.switch() assert f5_main2.f_code.co_name == 'main2' assert f3_foo.f_back is f1_bar# not running, so a loop +assert stack(f1_bar) == ['bar', 'foo', '...'] +# main() main2() res = c.switch() ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy vmprof-enable-kwargs: a branch where to implement the same _vmprof logic as in vmprof's enable-kwargs branch
Author: Antonio Cuni Branch: vmprof-enable-kwargs Changeset: r93026:ef1507afe550 Date: 2017-11-10 16:42 +0100 http://bitbucket.org/pypy/pypy/changeset/ef1507afe550/ Log:a branch where to implement the same _vmprof logic as in vmprof's enable-kwargs branch ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy continulet-no-frame-loop: WIP: add two temporary flags which allow to select: 1) the old switch logic vs the new one and 2) whether to print or not debug infos
Author: Antonio Cuni Branch: continulet-no-frame-loop Changeset: r93029:ba1ff85734b9 Date: 2017-11-15 01:43 +0100 http://bitbucket.org/pypy/pypy/changeset/ba1ff85734b9/ Log:WIP: add two temporary flags which allow to select: 1) the old switch logic vs the new one and 2) whether to print or not debug infos diff --git a/pypy/module/_continuation/interp_continuation.py b/pypy/module/_continuation/interp_continuation.py --- a/pypy/module/_continuation/interp_continuation.py +++ b/pypy/module/_continuation/interp_continuation.py @@ -41,7 +41,7 @@ bottomframe.locals_cells_stack_w[3] = w_kwds bottomframe.last_exception = get_cleared_operation_error(space) self.bottomframe = bottomframe -self.topframe = sthread.ec.topframeref # XXX? +self.topframeref = sthread.ec.topframeref # global_state.origin = self self.sthread = sthread @@ -79,11 +79,9 @@ global_state.origin = self if to is None: # simple switch: going to self.h -#print 'simple switch' global_state.destination = self else: # double switch: the final destination is to.h -#print 'double switch' global_state.destination = to # h = sthread.switch(global_state.destination.h) @@ -221,24 +219,6 @@ global_state = GlobalState() global_state.clear() - -def pstack(cont, message=''): -return -if message: -print message -if isinstance(cont, jit.DirectJitVRef): -f = cont() -else: -f = cont.bottomframe -i = 0 -while f: -print ' ', f.pycode.co_name -f = f.f_backref() -i += 1 -if i == 10: -break -print - def new_stacklet_callback(h, arg): self = global_state.origin self.h = h @@ -256,35 +236,66 @@ global_state.destination = self return self.h +DEBUG = False +ORIGINAL = False + +def log(x=''): +if DEBUG: +print x + +def pstack(cont, message=''): +""" +NOTE: I don't know exactly why, but sometimes if you pstack() a sthread or +a frame, then later you get an InvalidVirtualRef exception. So, in +general, this is a useful debugging tool but don't expect your tests to +pass if you call it. Put DEBUG=False to disable. +""" +if not DEBUG: +return +if message: +print message +if isinstance(cont, jit.DirectJitVRef): +f = cont() +else: +f = cont.bottomframe +i = 0 +while f: +print ' ', f.pycode.co_name +f = f.f_backref() +i += 1 +if i == 10: +break +print + def post_switch(sthread, h): origin = global_state.origin self = global_state.destination -#import pdb;pdb.set_trace() global_state.origin = None global_state.destination = None self.h, origin.h = origin.h, h # current = sthread.ec.topframeref -print ' SWITCH ' +lo +g(' SWITCH ') pstack(sthread.ec.topframeref, 'sthread.ec.topframeref') pstack(self, 'self') -# ORGINAL -## sthread.ec.topframeref = self.bottomframe.f_backref -## self.bottomframe.f_backref = origin.bottomframe.f_backref -## origin.bottomframe.f_backref = current - -# antocuni -sthread.ec.topframeref = self.topframe -self.topframe = origin.topframe -origin.topframe = current - +if ORIGINAL: +sthread.ec.topframeref = self.bottomframe.f_backref +self.bottomframe.f_backref = origin.bottomframe.f_backref +origin.bottomframe.f_backref = current +else: +# antocuni +sthread.ec.topframeref = self.topframeref +self.topframeref = origin.topframeref +origin.topframeref = current # -print 'swap' +log('swap') pstack(sthread.ec.topframeref, 'sthread.ec.topframeref') -pstack(self, 'self') -print ' END SWITCH ' -print +pstack(self +, 'self') +log(' END SWITCH ') +log() return get_result() def get_result(): @@ -315,7 +326,8 @@ if cont.sthread is None: continue # ignore non-initialized continulets else: -raise geterror(space, "inter-thread support is missing") +raise geterror(space +, "inter-thread support is missing") elif sthread.is_empty_handle(cont.h): raise geterror(space, "got an already-finished continulet") contlist.append(cont) ___ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit
[pypy-commit] pypy continulet-no-frame-loop: temporary checkin with some debugging stuff + a new logic to avoid building cycles of frames
Author: Antonio Cuni Branch: continulet-no-frame-loop Changeset: r93028:f7a1a6eb6908 Date: 2017-11-14 11:53 +0100 http://bitbucket.org/pypy/pypy/changeset/f7a1a6eb6908/ Log:temporary checkin with some debugging stuff + a new logic to avoid building cycles of frames diff --git a/pypy/module/_continuation/interp_continuation.py b/pypy/module/_continuation/interp_continuation.py --- a/pypy/module/_continuation/interp_continuation.py +++ b/pypy/module/_continuation/interp_continuation.py @@ -41,13 +41,16 @@ bottomframe.locals_cells_stack_w[3] = w_kwds bottomframe.last_exception = get_cleared_operation_error(space) self.bottomframe = bottomframe +self.topframe = sthread.ec.topframeref # XXX? # global_state.origin = self self.sthread = sthread +pstack(self, 'descr_init') h = sthread.new(new_stacklet_callback) post_switch(sthread, h) def switch(self, w_to): +#import pdb;pdb.set_trace() sthread = self.sthread to = self.space.interp_w(W_Continulet, w_to, can_be_None=True) if to is not None and to.sthread is None: @@ -76,9 +79,11 @@ global_state.origin = self if to is None: # simple switch: going to self.h +#print 'simple switch' global_state.destination = self else: # double switch: the final destination is to.h +#print 'double switch' global_state.destination = to # h = sthread.switch(global_state.destination.h) @@ -217,6 +222,23 @@ global_state.clear() +def pstack(cont, message=''): +return +if message: +print message +if isinstance(cont, jit.DirectJitVRef): +f = cont() +else: +f = cont.bottomframe +i = 0 +while f: +print ' ', f.pycode.co_name +f = f.f_backref() +i += 1 +if i == 10: +break +print + def new_stacklet_callback(h, arg): self = global_state.origin self.h = h @@ -225,6 +247,7 @@ frame = self.bottomframe w_result = frame.execute_frame() except Exception as e: +#import pdb;pdb.xpm() global_state.propagate_exception = e else: global_state.w_value = w_result @@ -236,15 +259,32 @@ def post_switch(sthread, h): origin = global_state.origin self = global_state.destination +#import pdb;pdb.set_trace() global_state.origin = None global_state.destination = None self.h, origin.h = origin.h, h # current = sthread.ec.topframeref -sthread.ec.topframeref = self.bottomframe.f_backref -self.bottomframe.f_backref = origin.bottomframe.f_backref -origin.bottomframe.f_backref = current +print ' SWITCH ' +pstack(sthread.ec.topframeref, 'sthread.ec.topframeref') +pstack(self, 'self') + +# ORGINAL +## sthread.ec.topframeref = self.bottomframe.f_backref +## self.bottomframe.f_backref = origin.bottomframe.f_backref +## origin.bottomframe.f_backref = current + +# antocuni +sthread.ec.topframeref = self.topframe +self.topframe = origin.topframe +origin.topframe = current + # +print 'swap' +pstack(sthread.ec.topframeref, 'sthread.ec.topframeref') +pstack(self, 'self') +print ' END SWITCH ' +print return get_result() def get_result(): diff --git a/pypy/module/_continuation/test/test_stacklet.py b/pypy/module/_continuation/test/test_stacklet.py --- a/pypy/module/_continuation/test/test_stacklet.py +++ b/pypy/module/_continuation/test/test_stacklet.py @@ -336,6 +336,47 @@ assert res == 2002 assert seen == [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13] +def test_xxx(self): +import sys +from _continuation import continulet +# +def stack(f=None): +""" +get the call-stack of the caller or the specified frame +""" +if f is None: +f = sys._getframe(1) +res = [] +seen = set() +while f: +if f in seen: +# frame loop +res.append('...') +break +seen.add(f) +res.append(f.f_code.co_name) +f = f.f_back +print res +return res + +def bar(c): +f = sys._getframe(0) +print 'bar 1' +c.switch(f) +print 'bar 2' +def foo(c): +bar(c) + +print +c = continulet(foo) +print 'test 1' +f = c.switch() +print 'test 2' +xxx = c.switch() +print 'xxx', xxx +#stack() +#stack(f) + def test_f_back(self): import sys from _continuation import continulet ___ pypy-commit mailing list pypy-commit@pyth