Author: fijal
Branch: py3.5
Changeset: r93534:4f88f2f2d3f2
Date: 2017-12-21 15:51 +0200
http://bitbucket.org/pypy/pypy/changeset/4f88f2f2d3f2/
Log: merge default
diff --git a/extra_tests/requirements.txt b/extra_tests/requirements.txt
--- a/extra_tests/requirements.txt
+++ b/extra_tests/requirements.txt
@@ -1,2 +1,3 @@
pytest
hypothesis
+vmprof
diff --git a/extra_tests/test_vmprof_greenlet.py
b/extra_tests/test_vmprof_greenlet.py
new file mode 100644
--- /dev/null
+++ b/extra_tests/test_vmprof_greenlet.py
@@ -0,0 +1,28 @@
+import time
+import pytest
+import greenlet
+vmprof = pytest.importorskip('vmprof')
+
+def count_samples(filename):
+ stats = vmprof.read_profile(filename)
+ return len(stats.profiles)
+
+def cpuburn(duration):
+ end = time.time() + duration
+ while time.time() < end:
+ pass
+
+def test_sampling_inside_callback(tmpdir):
+ # see also test_sampling_inside_callback inside
+ # pypy/module/_continuation/test/test_stacklet.py
+ #
+ G = greenlet.greenlet(cpuburn)
+ fname = tmpdir.join('log.vmprof')
+ with fname.open('w+b') as f:
+ vmprof.enable(f.fileno(), 1/250.0)
+ G.switch(0.1)
+ vmprof.disable()
+
+ samples = count_samples(str(fname))
+ # 0.1 seconds at 250Hz should be 25 samples
+ assert 23 < samples < 27
diff --git a/lib-python/2.7/subprocess.py b/lib-python/2.7/subprocess.py
--- a/lib-python/2.7/subprocess.py
+++ b/lib-python/2.7/subprocess.py
@@ -1296,7 +1296,7 @@
'copyfile' in caller.f_globals):
dest_dir = sys.pypy_resolvedirof(target_executable)
src_dir = sys.pypy_resolvedirof(sys.executable)
- for libname in ['libpypy-c.so', 'libpypy-c.dylib']:
+ for libname in ['libpypy-c.so', 'libpypy-c.dylib', 'libpypy-c.dll']:
dest_library = os.path.join(dest_dir, libname)
src_library = os.path.join(src_dir, libname)
if os.path.exists(src_library):
diff --git a/pypy/doc/index-of-release-notes.rst
b/pypy/doc/index-of-release-notes.rst
--- a/pypy/doc/index-of-release-notes.rst
+++ b/pypy/doc/index-of-release-notes.rst
@@ -6,6 +6,7 @@
.. toctree::
+ release-v5.10.0.rst
release-v5.9.0.rst
release-v5.8.0.rst
release-v5.7.1.rst
diff --git a/pypy/doc/release-v5.10.0.rst b/pypy/doc/release-v5.10.0.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/release-v5.10.0.rst
@@ -0,0 +1,94 @@
+======================================
+PyPy2.7 and PyPy3.5 v5.10 dual release
+======================================
+
+The PyPy team is proud to release both PyPy2.7 v5.10 (an interpreter supporting
+Python 2.7 syntax), and a final PyPy3.5 v5.10 (an interpreter for Python
+3.5 syntax). The two releases are both based on much the same codebase, thus
+the dual release.
+
+This release is an incremental release with very few new features, the main
+feature being the final PyPy3.5 release that works on linux and OS X with beta
+windows support. It also includes fixes for `vmprof`_ cooperation with
greenlets.
+
+Compared to 5.9, the 5.10 release contains mostly bugfixes and small
improvements.
+We have in the pipeline big new features coming for PyPy 6.0 that did not make
+the release cut and should be available within the next couple months.
+
+As always, this release is 100% compatible with the previous one and fixed
+several issues and bugs raised by the growing community of PyPy users.
+As always, we strongly recommend updating.
+
+This release concludes the Mozilla Open Source `grant`_ for having a compatible
+PyPy 3.5 release and we're very grateful for that. Of course, we will continue
+to improve PyPy 3.5 and probably move to 3.6 during the course of 2018.
+
+You can download the v5.10 releases here:
+
+ http://pypy.org/download.html
+
+We would like to thank our donors for the continued support of the PyPy
+project.
+
+We would also like to thank our contributors and
+encourage new people to join the project. PyPy has many
+layers and we need help with all of them: `PyPy`_ and `RPython`_ documentation
+improvements, tweaking popular `modules`_ to run on pypy, or general `help`_
+with making RPython's JIT even better.
+
+.. _vmprof: http://vmprof.readthedocs.io
+.. _grant:
https://morepypy.blogspot.com/2016/08/pypy-gets-funding-from-mozilla-for.html
+.. _`PyPy`: index.html
+.. _`RPython`: https://rpython.readthedocs.org
+.. _`modules`: project-ideas.html#make-more-python-modules-pypy-friendly
+.. _`help`: project-ideas.html
+
+What is PyPy?
+=============
+
+PyPy is a very compliant Python interpreter, almost a drop-in replacement for
+CPython 2.7 and CPython 3.5. It's fast (`PyPy and CPython 2.7.x`_ performance
comparison)
+due to its integrated tracing JIT compiler.
+
+We also welcome developers of other `dynamic languages`_ to see what RPython
+can do for them.
+
+The PyPy 2.7 release supports:
+
+ * **x86** machines on most common operating systems
+ (Linux 32/64 bits, Mac OS X 64 bits, Windows 32 bits, OpenBSD, FreeBSD)
+
+ * newer **ARM** hardware (ARMv6 or ARMv7, with VFPv3) running Linux,
+
+ * big- and little-endian variants of **PPC64** running Linux,
+
+ * **s390x** running Linux
+
+.. _`PyPy and CPython 2.7.x`: http://speed.pypy.org
+.. _`dynamic languages`: http://rpython.readthedocs.io/en/latest/examples.html
+
+Changelog
+=========
+
+* improve ssl handling on windows for pypy3 (makes pip work)
+* improve unicode handling in various error reporters
+* fix vmprof cooperation with greenlets
+* fix some things in cpyext
+* test and document the cmp(nan, nan) == 0 behaviour
+* don't crash when calling sleep with inf or nan
+* fix bugs in _io module
+* inspect.isbuiltin() now returns True for functions implemented in C
+* allow the sequences future-import, docstring, future-import for CPython bug
compatibility
+* Issue #2699: non-ascii messages in warnings
+* posix.lockf
+* fixes for FreeBSD platform
+* add .debug files, so builds contain debugging info, instead of being stripped
+* improvements to cppyy
+* issue #2677 copy pure c PyBuffer_{From,To}Contiguous from cpython
+* issue #2682, split firstword on any whitespace in sqlite3
+* ctypes: allow ptr[0] = foo when ptr is a pointer to struct
+* matplotlib will work with tkagg backend once `matplotlib pr #9356`_ is merged
+* improvements to utf32 surrogate handling
+* cffi version bump to 1.11.2
+
+.. _`matplotlib pr #9356`: https://github.com/matplotlib/matplotlib/pull/9356
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
@@ -31,7 +31,7 @@
Upgrade the _vmprof backend to vmprof 0.4.10
.. branch: fix-vmprof-stacklet-switch
-
+.. branch: fix-vmprof-stacklet-switch-2
Fix a vmprof+continulets (i.e. greenelts, eventlet, gevent, ...)
.. branch: win32-vcvars
@@ -39,3 +39,4 @@
.. branch: rdict-fast-hash
Make it possible to declare that the hash function of an r_dict is fast in
RPython.
+
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
@@ -1,5 +1,6 @@
from rpython.rlib.rstacklet import StackletThread
from rpython.rlib import jit
+from rpython.rlib import rvmprof
from pypy.interpreter.error import OperationError, get_cleared_operation_error
from pypy.interpreter.error import oefmt
from pypy.interpreter.executioncontext import ExecutionContext
@@ -241,12 +242,15 @@
self.h = h
global_state.clear()
try:
+ rvmprof.start_sampling()
frame = self.bottomframe
w_result = frame.execute_frame()
except Exception as e:
global_state.propagate_exception = e
else:
global_state.w_value = w_result
+ finally:
+ rvmprof.stop_sampling()
self.sthread.ec.topframeref = jit.vref_None
global_state.origin = self
global_state.destination = self
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
@@ -1,7 +1,10 @@
+import pytest
import os
+from rpython.rlib.rvmprof.test.support import fakevmprof
+from pypy.interpreter.gateway import interp2app
from pypy.module._continuation.test.support import BaseAppTest
-
[email protected]('app_fakevmprof')
class AppTestStacklet(BaseAppTest):
def setup_class(cls):
BaseAppTest.setup_class.im_func(cls)
@@ -34,6 +37,33 @@
return res
return stack
""")
+ cls.w_appdirect = cls.space.wrap(cls.runappdirect)
+ if cls.runappdirect:
+ # make sure that "self.stack" does not pass the self
+ cls.w_stack = staticmethod(cls.w_stack.im_func)
+
+
+ @pytest.fixture
+ def app_fakevmprof(self, fakevmprof):
+ """
+ This is automaticaly re-initialized for every method: thanks to
+ fakevmprof's finalizer, it checks that we called {start,stop}_sampling
+ the in pairs
+ """
+ w = self.space.wrap
+ i2a = interp2app
+ def is_sampling_enabled(space):
+ return space.wrap(fakevmprof.is_sampling_enabled)
+ self.w_is_sampling_enabled = w(i2a(is_sampling_enabled))
+ #
+ def start_sampling(space):
+ fakevmprof.start_sampling()
+ self.w_start_sampling = w(i2a(start_sampling))
+ #
+ def stop_sampling(space):
+ fakevmprof.stop_sampling()
+ self.w_stop_sampling = w(i2a(stop_sampling))
+
def test_new_empty(self):
from _continuation import continulet
@@ -797,3 +827,25 @@
bd50 = continulet(f)
main.switch(to=bd50)
print(999)
+
+ def test_sampling_inside_callback(self):
+ if self.appdirect:
+ # see also
+ # extra_tests.test_vmprof_greenlet.test_sampling_inside_callback
+ # for a "translated" version of this test
+ skip("we can't run this until we have _vmprof.is_sampling_enabled")
+ from _continuation import continulet
+ #
+ def my_callback(c1):
+ assert self.is_sampling_enabled()
+ return 42
+ #
+ try:
+ self.start_sampling()
+ assert self.is_sampling_enabled()
+ c = continulet(my_callback)
+ res = c.switch()
+ assert res == 42
+ assert self.is_sampling_enabled()
+ finally:
+ self.stop_sampling()
diff --git a/pypy/module/_continuation/test/test_translated.py
b/pypy/module/_continuation/test/test_translated.py
--- a/pypy/module/_continuation/test/test_translated.py
+++ b/pypy/module/_continuation/test/test_translated.py
@@ -1,4 +1,5 @@
import py
+import pytest
try:
import _continuation
except ImportError:
@@ -101,11 +102,7 @@
particular, we need to ensure that vmprof does not sample the stack in
the middle of a switch, else we read nonsense.
"""
- try:
- import _vmprof
- except ImportError:
- py.test.skip("no _vmprof")
- #
+ _vmprof = pytest.importorskip('_vmprof')
def switch_forever(c):
while True:
c.switch()
diff --git a/rpython/rlib/rstacklet.py b/rpython/rlib/rstacklet.py
--- a/rpython/rlib/rstacklet.py
+++ b/rpython/rlib/rstacklet.py
@@ -3,7 +3,7 @@
from rpython.rlib import jit
from rpython.rlib.objectmodel import fetch_translated_config
from rpython.rtyper.lltypesystem import lltype, llmemory
-from rpython.rlib.rvmprof import cintf
+from rpython.rlib import rvmprof
DEBUG = False
@@ -25,12 +25,12 @@
def new(self, callback, arg=llmemory.NULL):
if DEBUG:
callback = _debug_wrapper(callback)
- x = cintf.save_rvmprof_stack()
+ x = rvmprof.save_stack()
try:
- cintf.empty_rvmprof_stack()
+ rvmprof.empty_stack()
h = self._gcrootfinder.new(self, callback, arg)
finally:
- cintf.restore_rvmprof_stack(x)
+ rvmprof.restore_stack(x)
if DEBUG:
debug.add(h)
return h
@@ -40,11 +40,11 @@
def switch(self, stacklet):
if DEBUG:
debug.remove(stacklet)
- x = cintf.save_rvmprof_stack()
+ x = rvmprof.save_stack()
try:
h = self._gcrootfinder.switch(stacklet)
finally:
- cintf.restore_rvmprof_stack(x)
+ rvmprof.restore_stack(x)
if DEBUG:
debug.add(h)
return h
diff --git a/rpython/rlib/rvmprof/__init__.py b/rpython/rlib/rvmprof/__init__.py
--- a/rpython/rlib/rvmprof/__init__.py
+++ b/rpython/rlib/rvmprof/__init__.py
@@ -56,10 +56,27 @@
return None
def stop_sampling():
- from rpython.rlib.rvmprof.cintf import vmprof_stop_sampling
- fd = vmprof_stop_sampling()
- return rffi.cast(lltype.Signed, fd)
+ return _get_vmprof().stop_sampling()
def start_sampling():
- from rpython.rlib.rvmprof.cintf import vmprof_start_sampling
- vmprof_start_sampling()
+ return _get_vmprof().start_sampling()
+
+# ----------------
+# stacklet support
+# ----------------
+#
+# Ideally, vmprof_tl_stack, VMPROFSTACK etc. should be part of "self.cintf":
+# not sure why they are a global. Eventually, we should probably fix all this
+# mess.
+from rpython.rlib.rvmprof.cintf import vmprof_tl_stack, VMPROFSTACK
+
+def save_stack():
+ stop_sampling()
+ return vmprof_tl_stack.get_or_make_raw()
+
+def empty_stack():
+ vmprof_tl_stack.setraw(lltype.nullptr(VMPROFSTACK))
+
+def restore_stack(x):
+ vmprof_tl_stack.setraw(x)
+ start_sampling()
diff --git a/rpython/rlib/rvmprof/cintf.py b/rpython/rlib/rvmprof/cintf.py
--- a/rpython/rlib/rvmprof/cintf.py
+++ b/rpython/rlib/rvmprof/cintf.py
@@ -10,71 +10,82 @@
from rpython.rlib import rthread, jit
from rpython.rlib.objectmodel import we_are_translated
from rpython.config.translationoption import get_translation_config
+from rpython.jit.backend import detect_cpu
class VMProfPlatformUnsupported(Exception):
pass
+# vmprof works only on x86 for now
+IS_SUPPORTED = detect_cpu.autodetect().startswith('x86')
+if sys.platform == 'win32':
+ IS_SUPPORTED = False
+
ROOT = py.path.local(rpythonroot).join('rpython', 'rlib', 'rvmprof')
SRC = ROOT.join('src')
SHARED = SRC.join('shared')
BACKTRACE = SHARED.join('libbacktrace')
-compile_extra = ['-DRPYTHON_VMPROF']
-separate_module_files = [
- SHARED.join('symboltable.c'),
- SHARED.join('vmprof_unix.c')
-]
-if sys.platform.startswith('linux'):
- separate_module_files += [
- BACKTRACE.join('atomic.c'),
- BACKTRACE.join('backtrace.c'),
- BACKTRACE.join('state.c'),
- BACKTRACE.join('elf.c'),
- BACKTRACE.join('dwarf.c'),
- BACKTRACE.join('fileline.c'),
- BACKTRACE.join('mmap.c'),
- BACKTRACE.join('mmapio.c'),
- BACKTRACE.join('posix.c'),
- BACKTRACE.join('sort.c'),
+def make_eci():
+ if make_eci.called:
+ raise ValueError("make_eci() should be called at most once")
+ #
+ compile_extra = ['-DRPYTHON_VMPROF']
+ separate_module_files = [
+ SHARED.join('symboltable.c'),
+ SHARED.join('vmprof_unix.c')
]
- _libs = ['dl']
- compile_extra += ['-DVMPROF_UNIX']
- compile_extra += ['-DVMPROF_LINUX']
-elif sys.platform == 'win32':
- compile_extra += ['-DVMPROF_WINDOWS']
- separate_module_files = [SHARED.join('vmprof_win.c')]
- _libs = []
-else:
- # Guessing a BSD-like Unix platform
- compile_extra += ['-DVMPROF_UNIX']
- compile_extra += ['-DVMPROF_MAC']
- if sys.platform.startswith('freebsd'):
- _libs = ['unwind']
+ if sys.platform.startswith('linux'):
+ separate_module_files += [
+ BACKTRACE.join('atomic.c'),
+ BACKTRACE.join('backtrace.c'),
+ BACKTRACE.join('state.c'),
+ BACKTRACE.join('elf.c'),
+ BACKTRACE.join('dwarf.c'),
+ BACKTRACE.join('fileline.c'),
+ BACKTRACE.join('mmap.c'),
+ BACKTRACE.join('mmapio.c'),
+ BACKTRACE.join('posix.c'),
+ BACKTRACE.join('sort.c'),
+ ]
+ _libs = ['dl']
+ compile_extra += ['-DVMPROF_UNIX']
+ compile_extra += ['-DVMPROF_LINUX']
+ elif sys.platform == 'win32':
+ compile_extra += ['-DVMPROF_WINDOWS']
+ separate_module_files = [SHARED.join('vmprof_win.c')]
+ _libs = []
else:
- _libs = []
+ # Guessing a BSD-like Unix platform
+ compile_extra += ['-DVMPROF_UNIX']
+ compile_extra += ['-DVMPROF_MAC']
+ if sys.platform.startswith('freebsd'):
+ _libs = ['unwind']
+ else:
+ _libs = []
-
-eci_kwds = dict(
- include_dirs = [SRC, SHARED, BACKTRACE],
- includes = ['rvmprof.h','vmprof_stack.h'],
- libraries = _libs,
- separate_module_files = [
- SRC.join('rvmprof.c'),
- SHARED.join('compat.c'),
- SHARED.join('machine.c'),
- SHARED.join('vmp_stack.c'),
- SHARED.join('vmprof_memory.c'),
- SHARED.join('vmprof_common.c'),
- # symbol table already in separate_module_files
- ] + separate_module_files,
- post_include_bits=[],
- compile_extra=compile_extra
- )
-if sys.platform != 'win32':
- eci_kwds['separate_module_files'].append(
- SHARED.join('vmprof_mt.c'),
- )
-global_eci = ExternalCompilationInfo(**eci_kwds)
+ eci_kwds = dict(
+ include_dirs = [SRC, SHARED, BACKTRACE],
+ includes = ['rvmprof.h','vmprof_stack.h'],
+ libraries = _libs,
+ separate_module_files = [
+ SRC.join('rvmprof.c'),
+ SHARED.join('compat.c'),
+ SHARED.join('machine.c'),
+ SHARED.join('vmp_stack.c'),
+ SHARED.join('vmprof_memory.c'),
+ SHARED.join('vmprof_common.c'),
+ # symbol table already in separate_module_files
+ ] + separate_module_files,
+ post_include_bits=[],
+ compile_extra=compile_extra
+ )
+ if sys.platform != 'win32':
+ eci_kwds['separate_module_files'].append(
+ SHARED.join('vmprof_mt.c'),
+ )
+ make_eci.called = True
+ return ExternalCompilationInfo(**eci_kwds), eci_kwds
+make_eci.called = False
def configure_libbacktrace_linux():
bits = 32 if sys.maxsize == 2**31-1 else 64
@@ -85,14 +96,17 @@
shutil.copy(str(BACKTRACE.join(specific_config)), str(config))
def setup():
+ if not IS_SUPPORTED:
+ raise VMProfPlatformUnsupported
+
if sys.platform.startswith('linux'):
configure_libbacktrace_linux()
+ eci, eci_kwds = make_eci()
eci_kwds['compile_extra'].append('-DRPYTHON_LL2CTYPES')
platform.verify_eci(ExternalCompilationInfo(
**eci_kwds))
- eci = global_eci
vmprof_init = rffi.llexternal("vmprof_init",
[rffi.INT, rffi.DOUBLE, rffi.INT, rffi.INT,
rffi.CCHARP, rffi.INT, rffi.INT],
@@ -122,32 +136,16 @@
lltype.Signed,
compilation_info=eci,
_nowrapper=True)
+ vmprof_stop_sampling = rffi.llexternal("vmprof_stop_sampling", [],
+ rffi.INT, compilation_info=eci,
+ _nowrapper=True)
+ vmprof_start_sampling = rffi.llexternal("vmprof_start_sampling", [],
+ lltype.Void, compilation_info=eci,
+ _nowrapper=True)
+
return CInterface(locals())
-# this is always present, but compiles to no-op if RPYTHON_VMPROF is not
-# defined (i.e. if we don't actually use vmprof in the generated C)
-auto_eci = ExternalCompilationInfo(post_include_bits=["""
-#ifndef RPYTHON_VMPROF
-# define vmprof_stop_sampling() (-1)
-# define vmprof_start_sampling() ((void)0)
-#endif
-"""])
-
-if get_translation_config() is None:
- # tests need the full eci here
- _eci = global_eci
-else:
- _eci = auto_eci
-
-vmprof_stop_sampling = rffi.llexternal("vmprof_stop_sampling", [],
- rffi.INT, compilation_info=_eci,
- _nowrapper=True)
-vmprof_start_sampling = rffi.llexternal("vmprof_start_sampling", [],
- lltype.Void, compilation_info=_eci,
- _nowrapper=True)
-
-
class CInterface(object):
def __init__(self, namespace):
for k, v in namespace.iteritems():
@@ -232,20 +230,6 @@
leave_code(s)
#
-# stacklet support
-
-def save_rvmprof_stack():
- vmprof_stop_sampling()
- return vmprof_tl_stack.get_or_make_raw()
-
-def empty_rvmprof_stack():
- vmprof_tl_stack.setraw(lltype.nullptr(VMPROFSTACK))
-
-def restore_rvmprof_stack(x):
- vmprof_tl_stack.setraw(x)
- vmprof_start_sampling()
-
-#
# traceback support
def get_rvmprof_stack():
diff --git a/rpython/rlib/rvmprof/dummy.py b/rpython/rlib/rvmprof/dummy.py
new file mode 100644
--- /dev/null
+++ b/rpython/rlib/rvmprof/dummy.py
@@ -0,0 +1,26 @@
+from rpython.rlib.objectmodel import specialize
+
+class DummyVMProf(object):
+
+ def __init__(self):
+ self._unique_id = 0
+
+ def register_code_object_class(self, CodeClass, full_name_func):
+ CodeClass._vmprof_unique_id = self._unique_id
+ self._unique_id += 1
+
+ @specialize.argtype(1)
+ def register_code(self, code, full_name_func):
+ pass
+
+ def enable(self, fileno, interval, memory=0, native=0, real_time=0):
+ pass
+
+ def disable(self):
+ pass
+
+ def start_sampling(self):
+ pass
+
+ def stop_sampling(self):
+ pass
diff --git a/rpython/rlib/rvmprof/rvmprof.py b/rpython/rlib/rvmprof/rvmprof.py
--- a/rpython/rlib/rvmprof/rvmprof.py
+++ b/rpython/rlib/rvmprof/rvmprof.py
@@ -2,6 +2,7 @@
from rpython.rlib.objectmodel import specialize, we_are_translated, not_rpython
from rpython.rlib import jit, rposix, rgc
from rpython.rlib.rvmprof import cintf
+from rpython.rlib.rvmprof.dummy import DummyVMProf
from rpython.rtyper.annlowlevel import cast_instance_to_gcref
from rpython.rtyper.annlowlevel import cast_base_ptr_to_instance
from rpython.rtyper.lltypesystem import lltype, llmemory, rffi
@@ -34,6 +35,9 @@
return []
class VMProf(object):
+ """
+ NOTE: the API of this class should be kept in sync with dummy.DummyVMProf
+ """
_immutable_fields_ = ['is_enabled?']
@@ -168,6 +172,21 @@
if self.cintf.vmprof_register_virtual_function(name, uid, 500000) < 0:
raise VMProfError("vmprof buffers full! disk full or too slow")
+ def stop_sampling(self):
+ """
+ Temporarily stop the sampling of stack frames. Signals are still
+ delivered, but are ignored.
+ """
+ fd = self.cintf.vmprof_stop_sampling()
+ return rffi.cast(lltype.Signed, fd)
+
+ def start_sampling(self):
+ """
+ Undo the effect of stop_sampling
+ """
+ self.cintf.vmprof_start_sampling()
+
+
def vmprof_execute_code(name, get_code_fn, result_class=None,
_hack_update_stack_untranslated=False):
"""Decorator to be used on the function that interprets a code object.
@@ -240,5 +259,8 @@
def _get_vmprof():
global _vmprof_instance
if _vmprof_instance is None:
- _vmprof_instance = VMProf()
+ try:
+ _vmprof_instance = VMProf()
+ except cintf.VMProfPlatformUnsupported:
+ _vmprof_instance = DummyVMProf()
return _vmprof_instance
diff --git a/rpython/rlib/rvmprof/test/support.py
b/rpython/rlib/rvmprof/test/support.py
new file mode 100644
--- /dev/null
+++ b/rpython/rlib/rvmprof/test/support.py
@@ -0,0 +1,45 @@
+import pytest
+from rpython.rlib import rvmprof
+
+class FakeVMProf(object):
+
+ def __init__(self):
+ self._enabled = False
+ self._ignore_signals = 1
+
+ # --- VMProf official API ---
+ # add fake methods as needed by the tests
+
+ def stop_sampling(self):
+ self._ignore_signals += 1
+
+ def start_sampling(self):
+ assert self._ignore_signals > 0, ('calling start_sampling() without '
+ 'the corresponding stop_sampling()?')
+ self._ignore_signals -= 1
+
+ # --- FakeVMProf specific API ---
+ # this API is not part of rvmprof, but available only inside tests using
+ # fakevmprof
+
+ @property
+ def is_sampling_enabled(self):
+ return self._ignore_signals == 0
+
+ def check_status(self):
+ """
+ To be called during test teardown
+ """
+ if self._ignore_signals != 1:
+ msg = ('Invalid value for fakevmprof._ignore_signals: expected 1, '
+ 'got %d. This probably means that you called '
+ '{start,stop}_sampling() a wrong number of times')
+ raise ValueError, msg % self._ignore_signals
+
+
[email protected]
+def fakevmprof(request, monkeypatch):
+ fake = FakeVMProf()
+ monkeypatch.setattr(rvmprof.rvmprof, '_vmprof_instance', fake)
+ request.addfinalizer(fake.check_status)
+ return fake
diff --git a/rpython/rlib/rvmprof/test/test_support.py
b/rpython/rlib/rvmprof/test/test_support.py
new file mode 100644
--- /dev/null
+++ b/rpython/rlib/rvmprof/test/test_support.py
@@ -0,0 +1,42 @@
+import pytest
+from rpython.rlib import rvmprof
+from rpython.rlib.rvmprof.test.support import FakeVMProf, fakevmprof
+
+class TestFakeVMProf(object):
+
+ def test_sampling(self):
+ fake = FakeVMProf()
+ assert not fake.is_sampling_enabled
+ #
+ fake.start_sampling()
+ assert fake.is_sampling_enabled
+ #
+ fake.stop_sampling()
+ fake.stop_sampling()
+ assert not fake.is_sampling_enabled
+ #
+ fake.start_sampling()
+ assert not fake.is_sampling_enabled
+ fake.start_sampling()
+ assert fake.is_sampling_enabled
+ #
+ pytest.raises(AssertionError, "fake.start_sampling()")
+
+ def test_check_status(self):
+ fake = FakeVMProf()
+ fake.stop_sampling()
+ pytest.raises(ValueError, "fake.check_status()")
+
+
+class TestFixture(object):
+
+ def test_fixture(self, fakevmprof):
+ assert isinstance(fakevmprof, FakeVMProf)
+ assert rvmprof._get_vmprof() is fakevmprof
+ #
+ # tweak sampling using the "real" API, and check that we actually used
+ # the fake
+ rvmprof.start_sampling()
+ assert fakevmprof.is_sampling_enabled
+ rvmprof.stop_sampling()
+ assert not fakevmprof.is_sampling_enabled
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit