Author: Manuel Jacob <m...@manueljacob.de>
Branch: py3.3
Changeset: r79229:c9a245e856b7
Date: 2015-08-25 12:38 +0200
http://bitbucket.org/pypy/pypy/changeset/c9a245e856b7/

Log:    hg merge py3k

diff too long, truncating to 2000 out of 3074 lines

diff --git a/lib_pypy/cffi.egg-info/PKG-INFO b/lib_pypy/cffi.egg-info/PKG-INFO
--- a/lib_pypy/cffi.egg-info/PKG-INFO
+++ b/lib_pypy/cffi.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
 Metadata-Version: 1.1
 Name: cffi
-Version: 1.2.0
+Version: 1.2.1
 Summary: Foreign Function Interface for Python calling C code.
 Home-page: http://cffi.readthedocs.org
 Author: Armin Rigo, Maciej Fijalkowski
diff --git a/lib_pypy/cffi/__init__.py b/lib_pypy/cffi/__init__.py
--- a/lib_pypy/cffi/__init__.py
+++ b/lib_pypy/cffi/__init__.py
@@ -4,8 +4,8 @@
 from .api import FFI, CDefError, FFIError
 from .ffiplatform import VerificationError, VerificationMissing
 
-__version__ = "1.2.0"
-__version_info__ = (1, 2, 0)
+__version__ = "1.2.1"
+__version_info__ = (1, 2, 1)
 
 # The verifier module file names are based on the CRC32 of a string that
 # contains the following version number.  It may be older than __version__
diff --git a/lib_pypy/cffi/_cffi_include.h b/lib_pypy/cffi/_cffi_include.h
--- a/lib_pypy/cffi/_cffi_include.h
+++ b/lib_pypy/cffi/_cffi_include.h
@@ -46,7 +46,7 @@
 # endif
 #else
 # include <stdint.h>
-# if (defined (__SVR4) && defined (__sun)) || defined(_AIX)
+# if (defined (__SVR4) && defined (__sun)) || defined(_AIX) || defined(__hpux)
 #  include <alloca.h>
 # endif
 #endif
diff --git a/lib_pypy/cffi/cparser.py b/lib_pypy/cffi/cparser.py
--- a/lib_pypy/cffi/cparser.py
+++ b/lib_pypy/cffi/cparser.py
@@ -15,9 +15,11 @@
 except ImportError:
     lock = None
 
-_r_comment = re.compile(r"/\*.*?\*/|//.*?$", re.DOTALL | re.MULTILINE)
-_r_define  = re.compile(r"^\s*#\s*define\s+([A-Za-z_][A-Za-z_0-9]*)\s+(.*?)$",
-                        re.MULTILINE)
+_r_comment = re.compile(r"/\*.*?\*/|//([^\n\\]|\\.)*?$",
+                        re.DOTALL | re.MULTILINE)
+_r_define  = re.compile(r"^\s*#\s*define\s+([A-Za-z_][A-Za-z_0-9]*)"
+                        r"\b((?:[^\n\\]|\\.)*?)$",
+                        re.DOTALL | re.MULTILINE)
 _r_partial_enum = re.compile(r"=\s*\.\.\.\s*[,}]|\.\.\.\s*\}")
 _r_enum_dotdotdot = re.compile(r"__dotdotdot\d+__$")
 _r_partial_array = re.compile(r"\[\s*\.\.\.\s*\]")
@@ -39,6 +41,7 @@
     macros = {}
     for match in _r_define.finditer(csource):
         macroname, macrovalue = match.groups()
+        macrovalue = macrovalue.replace('\\\n', '').strip()
         macros[macroname] = macrovalue
     csource = _r_define.sub('', csource)
     # Replace "[...]" with "[__dotdotdotarray__]"
@@ -423,13 +426,10 @@
                 raise api.CDefError(
                     "%s: a function with only '(...)' as argument"
                     " is not correct C" % (funcname or 'in expression'))
-        elif (len(params) == 1 and
-            isinstance(params[0].type, pycparser.c_ast.TypeDecl) and
-            isinstance(params[0].type.type, pycparser.c_ast.IdentifierType)
-                and list(params[0].type.type.names) == ['void']):
-            del params[0]
         args = [self._as_func_arg(self._get_type(argdeclnode.type))
                 for argdeclnode in params]
+        if not ellipsis and args == [model.void_type]:
+            args = []
         result = self._get_type(typenode.type)
         return model.RawFunctionType(tuple(args), result, ellipsis)
 
diff --git a/lib_pypy/cffi/recompiler.py b/lib_pypy/cffi/recompiler.py
--- a/lib_pypy/cffi/recompiler.py
+++ b/lib_pypy/cffi/recompiler.py
@@ -4,11 +4,6 @@
 
 VERSION = "0x2601"
 
-try:
-    int_type = (int, long)
-except NameError:    # Python 3
-    int_type = int
-
 
 class GlobalExpr:
     def __init__(self, name, address, type_op, size=0, check_value=0):
diff --git a/lib_pypy/cffi/setuptools_ext.py b/lib_pypy/cffi/setuptools_ext.py
--- a/lib_pypy/cffi/setuptools_ext.py
+++ b/lib_pypy/cffi/setuptools_ext.py
@@ -81,10 +81,16 @@
     allsources.extend(kwds.pop('sources', []))
     ext = Extension(name=module_name, sources=allsources, **kwds)
 
-    def make_mod(tmpdir):
+    def make_mod(tmpdir, pre_run=None):
         c_file = os.path.join(tmpdir, module_name + source_extension)
         log.info("generating cffi module %r" % c_file)
         mkpath(tmpdir)
+        # a setuptools-only, API-only hook: called with the "ext" and "ffi"
+        # arguments just before we turn the ffi into C code.  To use it,
+        # subclass the 'distutils.command.build_ext.build_ext' class and
+        # add a method 'def pre_run(self, ext, ffi)'.
+        if pre_run is not None:
+            pre_run(ext, ffi)
         updated = recompiler.make_c_source(ffi, module_name, source, c_file)
         if not updated:
             log.info("already up-to-date")
@@ -98,7 +104,8 @@
     class build_ext_make_mod(base_class):
         def run(self):
             if ext.sources[0] == '$PLACEHOLDER':
-                ext.sources[0] = make_mod(self.build_temp)
+                pre_run = getattr(self, 'pre_run', None)
+                ext.sources[0] = make_mod(self.build_temp, pre_run)
             base_class.run(self)
     dist.cmdclass['build_ext'] = build_ext_make_mod
     # NB. multiple runs here will create multiple 'build_ext_make_mod'
diff --git a/pypy/bin/pyinteractive.py b/pypy/bin/pyinteractive.py
--- a/pypy/bin/pyinteractive.py
+++ b/pypy/bin/pyinteractive.py
@@ -143,7 +143,8 @@
     if interactiveconfig.runmodule:
         command = args.pop(0)
     for arg in args:
-        space.call_method(space.sys.get('argv'), 'append', space.wrap(arg))
+        space.call_method(space.sys.get('argv'), 'append',
+                          space.wrap_fsdecoded(arg))
 
     # load the source of the program given as command-line argument
     if interactiveconfig.runcommand:
diff --git a/pypy/doc/index-of-whatsnew.rst b/pypy/doc/index-of-whatsnew.rst
--- a/pypy/doc/index-of-whatsnew.rst
+++ b/pypy/doc/index-of-whatsnew.rst
@@ -7,6 +7,7 @@
 .. toctree::
 
    whatsnew-head.rst
+   whatsnew-2.6.1.rst
    whatsnew-2.6.0.rst
    whatsnew-2.5.1.rst
    whatsnew-2.5.0.rst
diff --git a/pypy/doc/whatsnew-2.6.1.rst b/pypy/doc/whatsnew-2.6.1.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/whatsnew-2.6.1.rst
@@ -0,0 +1,72 @@
+========================
+What's new in PyPy 2.6.1
+========================
+
+.. this is a revision shortly after release-2.6.0
+.. startrev: 91904d5c5188
+
+.. branch: use_min_scalar
+Correctly resolve the output dtype of ufunc(array, scalar) calls.
+
+.. branch: stdlib-2.7.10
+
+Update stdlib to version 2.7.10
+
+.. branch: issue2062
+
+.. branch: disable-unroll-for-short-loops
+The JIT no longer performs loop unrolling if the loop compiles to too much 
code.
+
+.. branch: run-create_cffi_imports
+
+Build cffi import libraries as part of translation by monkey-patching an 
+additional task into translation
+
+.. branch: int-float-list-strategy
+
+Use a compact strategy for Python lists that mix integers and floats,
+at least if the integers fit inside 32 bits.  These lists are now
+stored as an array of floats, like lists that contain only floats; the
+difference is that integers are stored as tagged NaNs.  (This should
+have no visible effect!  After ``lst = [42, 42.5]``, the value of
+``lst[0]`` is still *not* the float ``42.0`` but the integer ``42``.)
+
+.. branch: cffi-callback-onerror
+Part of cffi 1.2.
+
+.. branch: cffi-new-allocator
+Part of cffi 1.2.
+
+.. branch: unicode-dtype
+
+Partial implementation of unicode dtype and unicode scalars.
+
+.. branch: dtypes-compatability
+
+Improve compatibility with numpy dtypes; handle offsets to create unions,
+fix str() and repr(), allow specifying itemsize, metadata and titles, add 
flags,
+allow subclassing dtype
+
+.. branch: indexing
+
+Refactor array indexing to support ellipses.
+
+.. branch: numpy-docstrings
+
+Allow the docstrings of built-in numpy objects to be set at run-time.
+
+.. branch: nditer-revisited
+
+Implement nditer 'buffered' flag and fix some edge cases
+
+.. branch: ufunc-reduce
+
+Allow multiple axes in ufunc.reduce()
+
+.. branch: fix-tinylang-goals
+
+Update tinylang goals to match current rpython
+
+.. branch: vmprof-review
+
+Clean up of vmprof, notably to handle correctly multiple threads
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
@@ -2,68 +2,6 @@
 What's new in PyPy 2.6+
 =======================
 
-.. this is a revision shortly after release-2.6.0
-.. startrev: 91904d5c5188
+.. this is a revision shortly after release-2.6.1
+.. startrev: 83ebc73d4fcb
 
-.. branch: use_min_scalar
-Correctly resolve the output dtype of ufunc(array, scalar) calls.
-
-.. branch: stdlib-2.7.10
-
-Update stdlib to version 2.7.10
-
-.. branch: issue2062
-
-.. branch: disable-unroll-for-short-loops
-The JIT no longer performs loop unrolling if the loop compiles to too much 
code.
-
-.. branch: run-create_cffi_imports
-
-Build cffi import libraries as part of translation by monkey-patching an 
-additional task into translation
-
-.. branch: int-float-list-strategy
-
-Use a compact strategy for Python lists that mix integers and floats,
-at least if the integers fit inside 32 bits.  These lists are now
-stored as an array of floats, like lists that contain only floats; the
-difference is that integers are stored as tagged NaNs.  (This should
-have no visible effect!  After ``lst = [42, 42.5]``, the value of
-``lst[0]`` is still *not* the float ``42.0`` but the integer ``42``.)
-
-.. branch: cffi-callback-onerror
-.. branch: cffi-new-allocator
-
-.. branch: unicode-dtype
-
-Partial implementation of unicode dtype and unicode scalars.
-
-.. branch: dtypes-compatability
-
-Improve compatibility with numpy dtypes; handle offsets to create unions,
-fix str() and repr(), allow specifying itemsize, metadata and titles, add 
flags,
-allow subclassing dtype
-
-.. branch: indexing
-
-Refactor array indexing to support ellipses.
-
-.. branch: numpy-docstrings
-
-Allow the docstrings of built-in numpy objects to be set at run-time.
-
-.. branch: nditer-revisited
-
-Implement nditer 'buffered' flag and fix some edge cases
-
-.. branch: ufunc-reduce
-
-Allow multiple axes in ufunc.reduce()
-
-.. branch: fix-tinylang-goals
-
-Update tinylang goals to match current rpython
-
-.. branch: vmprof-review
-
-Clean up of vmprof, notably to handle correctly multiple threads
diff --git a/pypy/goal/targetpypystandalone.py 
b/pypy/goal/targetpypystandalone.py
--- a/pypy/goal/targetpypystandalone.py
+++ b/pypy/goal/targetpypystandalone.py
@@ -61,8 +61,8 @@
                         rlocale.setlocale(rlocale.LC_CTYPE, '')
                     except rlocale.LocaleError:
                         pass
-                w_executable = space.fsdecode(space.wrapbytes(argv[0]))
-                w_argv = space.newlist([space.fsdecode(space.wrapbytes(s))
+                w_executable = space.wrap_fsdecoded(argv[0])
+                w_argv = space.newlist([space.wrap_fsdecoded(s)
                                         for s in argv[1:]])
                 w_exitcode = space.call_function(w_entry_point, w_executable, 
w_argv)
                 exitcode = space.int_w(w_exitcode)
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -1052,6 +1052,9 @@
         from pypy.objspace.std.listobject import make_empty_list_with_size
         return make_empty_list_with_size(self, sizehint)
 
+    def wrap_fsdecoded(self, x):
+        return self.fsdecode(self.wrapbytes(x))
+
     @jit.unroll_safe
     def exception_match(self, w_exc_type, w_check_class):
         """Checks if the given exception type matches 'w_check_class'."""
diff --git a/pypy/interpreter/main.py b/pypy/interpreter/main.py
--- a/pypy/interpreter/main.py
+++ b/pypy/interpreter/main.py
@@ -19,7 +19,8 @@
 def compilecode(space, source, filename, cmd='exec'):
     w = space.wrap
     w_code = space.builtin.call(
-        'compile', space.wrapbytes(source), w(filename), w(cmd), w(0), w(0))
+        'compile', space.wrapbytes(source), space.wrap_fsdecoded(filename),
+        w(cmd), w(0), w(0))
     pycode = space.interp_w(eval.Code, w_code)
     return pycode
 
@@ -44,7 +45,8 @@
 
         space.setitem(w_globals, w('__builtins__'), space.builtin)
         if filename is not None:
-            space.setitem(w_globals, w('__file__'), w(filename))
+            space.setitem(w_globals, w('__file__'),
+                          space.wrap_fsdecoded(filename))
 
         retval = pycode.exec_code(space, w_globals, w_globals)
         if eval:
diff --git a/pypy/module/_cffi_backend/__init__.py 
b/pypy/module/_cffi_backend/__init__.py
--- a/pypy/module/_cffi_backend/__init__.py
+++ b/pypy/module/_cffi_backend/__init__.py
@@ -2,7 +2,7 @@
 from pypy.interpreter.mixedmodule import MixedModule
 from rpython.rlib import rdynload
 
-VERSION = "1.2.0"
+VERSION = "1.2.1"
 
 
 class Module(MixedModule):
diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py 
b/pypy/module/_cffi_backend/test/_backend_test_c.py
--- a/pypy/module/_cffi_backend/test/_backend_test_c.py
+++ b/pypy/module/_cffi_backend/test/_backend_test_c.py
@@ -3427,4 +3427,4 @@
 
 def test_version():
     # this test is here mostly for PyPy
-    assert __version__ == "1.2.0"
+    assert __version__ == "1.2.1"
diff --git a/pypy/module/_vmprof/test/test__vmprof.py 
b/pypy/module/_vmprof/test/test__vmprof.py
--- a/pypy/module/_vmprof/test/test__vmprof.py
+++ b/pypy/module/_vmprof/test/test__vmprof.py
@@ -21,11 +21,12 @@
             i = 0
             count = 0
             i += 5 * WORD # header
-            assert s[i] == 4
-            i += 1 # marker
-            assert s[i] == 4
-            i += 1 # length
-            i += len('pypy')
+            assert s[i    ] == 5    # MARKER_HEADER
+            assert s[i + 1] == 0    # 0
+            assert s[i + 2] == 1    # VERSION_THREAD_ID
+            assert s[i + 3] == 4    # len('pypy')
+            assert s[i + 4: i + 8] == b'pypy'
+            i += 8
             while i < len(s):
                 if s[i] == 3:
                     break
diff --git a/pypy/module/_vmprof/test/test_direct.py 
b/pypy/module/_vmprof/test/test_direct.py
--- a/pypy/module/_vmprof/test/test_direct.py
+++ b/pypy/module/_vmprof/test/test_direct.py
@@ -42,7 +42,7 @@
 }
 
 
-""" + open(str(srcdir.join("rvmprof_get_custom_offset.h"))).read())
+""" + open(str(srcdir.join("vmprof_get_custom_offset.h"))).read())
 
 class TestDirect(object):
     def test_infrastructure(self):
diff --git a/pypy/module/cpyext/include/object.h 
b/pypy/module/cpyext/include/object.h
--- a/pypy/module/cpyext/include/object.h
+++ b/pypy/module/cpyext/include/object.h
@@ -364,6 +364,8 @@
     PyObject *ht_name, *ht_slots;
 } PyHeapTypeObject;
 
+#define PyObject_Bytes PyObject_Str
+
 /* Flag bits for printing: */
 #define Py_PRINT_RAW   1       /* No string quotes etc. */
 
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_parsing.py 
b/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_parsing.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_parsing.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_parsing.py
@@ -160,6 +160,35 @@
     assert func.name == 'sin'
     assert func.BType == '<func (<double>, <double>), <double>, False>'
 
+def test_remove_line_continuation_comments():
+    ffi = FFI(backend=FakeBackend())
+    ffi.cdef("""
+        double // blah \\
+                  more comments
+        x(void);
+        double // blah\\\\
+        y(void);
+        double // blah\\ \
+                  etc
+        z(void);
+    """)
+    m = ffi.dlopen(lib_m)
+    m.x
+    m.y
+    m.z
+
+def test_line_continuation_in_defines():
+    ffi = FFI(backend=FakeBackend())
+    ffi.cdef("""
+        #define ABC\\
+            42
+        #define BCD   \\
+            43
+    """)
+    m = ffi.dlopen(lib_m)
+    assert m.ABC == 42
+    assert m.BCD == 43
+
 def test_define_not_supported_for_now():
     ffi = FFI(backend=FakeBackend())
     e = py.test.raises(CDefError, ffi.cdef, '#define FOO "blah"')
@@ -238,6 +267,13 @@
     ffi = FFI()
     ffi.cdef("typedef _Bool bool; void f(bool);")
 
+def test_void_renamed_as_only_arg():
+    ffi = FFI()
+    ffi.cdef("typedef void void_t1;"
+             "typedef void_t1 void_t;"
+             "typedef int (*func_t)(void_t);")
+    assert ffi.typeof("func_t").args == ()
+
 def test_win_common_types():
     from cffi.commontypes import COMMON_TYPES, _CACHE
     from cffi.commontypes import win_common_types, resolve_common_type
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py 
b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py
@@ -25,6 +25,9 @@
     if 1:     # test the .cpp mode too
         kwds.setdefault('source_extension', '.cpp')
         source = 'extern "C" {\n%s\n}' % (source,)
+    else:
+        kwds['extra_compile_args'] = (kwds.get('extra_compile_args', []) +
+                                      ['-Werror'])
     return recompiler._verify(ffi, module_name, source, *args, **kwds)
 
 
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_zdist.py 
b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_zdist.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_zdist.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_zdist.py
@@ -318,15 +318,32 @@
                 import cffi
                 ffi = cffi.FFI()
                 ffi.set_source("pack3.mymod", "/*code would be here*/")
+                ffi._hi_there = 42
             """)
         with open("setup.py", "w") as f:
-            f.write("""if 1:
+            f.write("from __future__ import print_function\n"
+                """if 1:
                 from setuptools import setup
+                from distutils.command.build_ext import build_ext
+                import os
+
+                class TestBuildExt(build_ext):
+                    def pre_run(self, ext, ffi):
+                        print('_make_setuptools_api: in pre_run:', end=" ")
+                        assert ffi._hi_there == 42
+                        assert ext.name == "pack3.mymod"
+                        fn = os.path.join(os.path.dirname(self.build_lib),
+                                          '..', 'see_me')
+                        print('creating %r' % (fn,))
+                        open(fn, 'w').close()
+
                 setup(name='example1',
                       version='0.1',
                       packages=['pack3'],
                       package_dir={'': 'src1'},
-                      cffi_modules=["src1/pack3/_build.py:ffi"])
+                      cffi_modules=["src1/pack3/_build.py:ffi"],
+                      cmdclass={'build_ext': TestBuildExt},
+                      )
             """)
 
     @chdir_to_tmp
@@ -335,6 +352,7 @@
         self.run(["setup.py", "build"])
         self.check_produced_files({'setup.py': None,
                                    'build': '?',
+                                   'see_me': None,
                                    'src1': {'pack3': {'__init__.py': None,
                                                       '_build.py': None}}})
 
@@ -344,6 +362,7 @@
         self.run(["setup.py", "build_ext", "-i"])
         self.check_produced_files({'setup.py': None,
                                    'build': '?',
+                                   'see_me': None,
                                    'src1': {'pack3': {'__init__.py': None,
                                                       '_build.py': None,
                                                       'mymod.SO': None}}})
diff --git a/rpython/flowspace/objspace.py b/rpython/flowspace/objspace.py
--- a/rpython/flowspace/objspace.py
+++ b/rpython/flowspace/objspace.py
@@ -13,6 +13,11 @@
 
 def _assert_rpythonic(func):
     """Raise ValueError if ``func`` is obviously not RPython"""
+    try:
+        func.func_code.co_cellvars
+    except AttributeError:
+        raise ValueError("%r is not RPython: it is likely an unexpected "
+                         "built-in function or type" % (func,))
     if func.func_doc and func.func_doc.lstrip().startswith('NOT_RPYTHON'):
         raise ValueError("%r is tagged as NOT_RPYTHON" % (func,))
     if func.func_code.co_cellvars:
diff --git a/rpython/flowspace/test/test_objspace.py 
b/rpython/flowspace/test/test_objspace.py
--- a/rpython/flowspace/test/test_objspace.py
+++ b/rpython/flowspace/test/test_objspace.py
@@ -1363,6 +1363,15 @@
         simplify_graph(graph)
         assert self.all_operations(graph) == {'bool': 1, 'inplace_add': 1}
 
+    def test_unexpected_builtin_function(self):
+        import itertools
+        e = py.test.raises(ValueError, build_flow, itertools.permutations)
+        assert ' is not RPython:' in str(e.value)
+        e = py.test.raises(ValueError, build_flow, itertools.tee)
+        assert ' is not RPython:' in str(e.value)
+        e = py.test.raises(ValueError, build_flow, Exception.__init__)
+        assert ' is not RPython:' in str(e.value)
+
 
 DATA = {'x': 5,
         'y': 6}
diff --git a/rpython/jit/backend/arm/runner.py 
b/rpython/jit/backend/arm/runner.py
--- a/rpython/jit/backend/arm/runner.py
+++ b/rpython/jit/backend/arm/runner.py
@@ -64,12 +64,6 @@
                                               operations,
                                               original_loop_token, log=log)
 
-    def clear_latest_values(self, count):
-        setitem = self.assembler.fail_boxes_ptr.setitem
-        null = lltype.nullptr(llmemory.GCREF.TO)
-        for index in range(count):
-            setitem(index, null)
-
     def cast_ptr_to_int(x):
         adr = llmemory.cast_ptr_to_adr(x)
         return CPU_ARM.cast_adr_to_int(adr)
diff --git a/rpython/jit/backend/llsupport/regalloc.py 
b/rpython/jit/backend/llsupport/regalloc.py
--- a/rpython/jit/backend/llsupport/regalloc.py
+++ b/rpython/jit/backend/llsupport/regalloc.py
@@ -636,8 +636,7 @@
             assert isinstance(box, Box)
             loc = self.fm.get_new_loc(box)
             locs.append(loc.value - base_ofs)
-        if looptoken.compiled_loop_token is not None:
-            # for tests
+        if looptoken.compiled_loop_token is not None:   # <- for tests
             looptoken.compiled_loop_token._ll_initial_locs = locs
 
     def can_merge_with_next_guard(self, op, i, operations):
diff --git a/rpython/jit/backend/llsupport/src/codemap.c 
b/rpython/jit/backend/llsupport/src/codemap.c
--- a/rpython/jit/backend/llsupport/src/codemap.c
+++ b/rpython/jit/backend/llsupport/src/codemap.c
@@ -6,9 +6,9 @@
 #endif
 
 #ifdef RPYTHON_VMPROF
-RPY_EXTERN void rpython_vmprof_ignore_signals(int ignored);
+RPY_EXTERN void vmprof_ignore_signals(int ignored);
 static void pypy_codemap_invalid_set(int ignored) {
-    rpython_vmprof_ignore_signals(ignored);
+    vmprof_ignore_signals(ignored);
 }
 #else
 static void pypy_codemap_invalid_set(int ignored) {
diff --git a/rpython/jit/backend/x86/runner.py 
b/rpython/jit/backend/x86/runner.py
--- a/rpython/jit/backend/x86/runner.py
+++ b/rpython/jit/backend/x86/runner.py
@@ -100,12 +100,6 @@
         return self.assembler.assemble_bridge(faildescr, inputargs, operations,
                                               original_loop_token, log, logger)
 
-    def clear_latest_values(self, count):
-        setitem = self.assembler.fail_boxes_ptr.setitem
-        null = lltype.nullptr(llmemory.GCREF.TO)
-        for index in range(count):
-            setitem(index, null)
-
     def cast_ptr_to_int(x):
         adr = llmemory.cast_ptr_to_adr(x)
         return CPU386.cast_adr_to_int(adr)
diff --git a/rpython/jit/metainterp/test/test_ajit.py 
b/rpython/jit/metainterp/test/test_ajit.py
--- a/rpython/jit/metainterp/test/test_ajit.py
+++ b/rpython/jit/metainterp/test/test_ajit.py
@@ -268,6 +268,7 @@
                 y -= 1
             return res
         res = self.meta_interp(f, [6, sys.maxint, 48])
+        self.check_trace_count(6)
         assert res == f(6, sys.maxint, 48)
 
     def test_loop_invariant_mul_bridge_ovf2(self):
diff --git a/rpython/rlib/jit.py b/rpython/rlib/jit.py
--- a/rpython/rlib/jit.py
+++ b/rpython/rlib/jit.py
@@ -1087,6 +1087,16 @@
     """
     assert type(value) is cls
 
+def ll_record_exact_class(ll_value, ll_cls):
+    from rpython.rlib.debug import ll_assert
+    from rpython.rtyper.lltypesystem.lloperation import llop
+    from rpython.rtyper.lltypesystem import lltype
+    from rpython.rtyper.rclass import ll_type
+    ll_assert(ll_value == lltype.nullptr(lltype.typeOf(ll_value).TO), 
"record_exact_class called with None argument")
+    ll_assert(ll_type(ll_value) is ll_cls, "record_exact_class called with 
invalid arguments")
+    llop.jit_record_exact_class(lltype.Void, ll_value, ll_cls)
+
+
 class Entry(ExtRegistryEntry):
     _about_ = record_exact_class
 
@@ -1100,12 +1110,10 @@
         from rpython.rtyper import rclass
 
         classrepr = rclass.get_type_repr(hop.rtyper)
-
-        hop.exception_cannot_occur()
         v_inst = hop.inputarg(hop.args_r[0], arg=0)
         v_cls = hop.inputarg(classrepr, arg=1)
-        return hop.genop('jit_record_exact_class', [v_inst, v_cls],
-                         resulttype=lltype.Void)
+        hop.exception_is_here()
+        return hop.gendirectcall(ll_record_exact_class, v_inst, v_cls)
 
 def _jit_conditional_call(condition, function, *args):
     pass
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
@@ -40,24 +40,20 @@
         **eci_kwds))
 
 
-    vmprof_init = rffi.llexternal("rpython_vmprof_init", [rffi.INT], 
rffi.CCHARP,
-                                  compilation_info=eci)
-    vmprof_enable = rffi.llexternal("rpython_vmprof_enable", [rffi.LONG], 
rffi.INT,
+    vmprof_init = rffi.llexternal("vmprof_init",
+                                  [rffi.INT, rffi.DOUBLE, rffi.CCHARP],
+                                  rffi.CCHARP, compilation_info=eci)
+    vmprof_enable = rffi.llexternal("vmprof_enable", [], rffi.INT,
                                     compilation_info=eci,
                                     save_err=rffi.RFFI_SAVE_ERRNO)
-    vmprof_disable = rffi.llexternal("rpython_vmprof_disable", [], rffi.INT,
+    vmprof_disable = rffi.llexternal("vmprof_disable", [], rffi.INT,
                                      compilation_info=eci,
                                      save_err=rffi.RFFI_SAVE_ERRNO)
-    vmprof_write_buf = rffi.llexternal("rpython_vmprof_write_buf",
-                                       [rffi.CCHARP, rffi.LONG],
-                                       lltype.Void, compilation_info=eci)
-
-    ## vmprof_register_virtual_function = rffi.llexternal(
-    ##     "vmprof_register_virtual_function",
-    ##     [rffi.CCHARP, rffi.VOIDP, rffi.VOIDP], lltype.Void,
-    ##     compilation_info=eci, _nowrapper=True)
-
-    vmprof_ignore_signals = rffi.llexternal("rpython_vmprof_ignore_signals",
+    vmprof_register_virtual_function = rffi.llexternal(
+                                           "vmprof_register_virtual_function",
+                                           [rffi.CCHARP, rffi.LONG, rffi.INT],
+                                           rffi.INT, compilation_info=eci)
+    vmprof_ignore_signals = rffi.llexternal("vmprof_ignore_signals",
                                             [rffi.INT], lltype.Void,
                                             compilation_info=eci)
     return CInterface(locals())
@@ -83,10 +79,20 @@
 
     cont_name = 'rpyvmprof_f_%s_%s' % (name, token)
     tramp_name = 'rpyvmprof_t_%s_%s' % (name, token)
+    orig_tramp_name = tramp_name
 
     func.c_name = cont_name
     func._dont_inline_ = True
 
+    if sys.platform == 'darwin':
+        # according to internet "At the time UNIX was written in 1974...."
+        # "... all C functions are prefixed with _"
+        cont_name = '_' + cont_name
+        tramp_name = '_' + tramp_name
+        PLT = ""
+    else:
+        PLT = "@PLT"
+
     assert detect_cpu.autodetect().startswith(detect_cpu.MODEL_X86_64), (
         "rvmprof only supports x86-64 CPUs for now")
 
@@ -111,17 +117,15 @@
     target.write("""\
 \t.text
 \t.globl\t%(tramp_name)s
-\t.type\t%(tramp_name)s, @function
 %(tramp_name)s:
 \t.cfi_startproc
 \tpushq\t%(reg)s
 \t.cfi_def_cfa_offset 16
-\tcall %(cont_name)s@PLT
+\tcall %(cont_name)s%(PLT)s
 \taddq\t$8, %%rsp
 \t.cfi_def_cfa_offset 8
 \tret
 \t.cfi_endproc
-\t.size\t%(tramp_name)s, .-%(tramp_name)s
 """ % locals())
 
     def tok2cname(tok):
@@ -133,7 +137,7 @@
 
     header = 'RPY_EXTERN %s %s(%s);\n' % (
         tok2cname(restok),
-        tramp_name,
+        orig_tramp_name,
         ', '.join([tok2cname(tok) for tok in token] + ['long']))
 
     header += """\
@@ -147,7 +151,7 @@
 #endif
 #define VMPROF_ADDR_OF_TRAMPOLINE cmp_%s
 }
-""" % (tramp_name, tramp_name, tramp_name)
+""" % (tramp_name, orig_tramp_name, tramp_name)
 
     eci = ExternalCompilationInfo(
         post_include_bits = [header],
@@ -155,7 +159,7 @@
     )
 
     return rffi.llexternal(
-        tramp_name,
+        orig_tramp_name,
         [token2lltype(tok) for tok in token] + [lltype.Signed],
         token2lltype(restok),
         compilation_info=eci,
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
@@ -1,14 +1,12 @@
 import sys, os
 from rpython.rlib.objectmodel import specialize, we_are_translated
-from rpython.rlib.rstring import StringBuilder
 from rpython.rlib import jit, rgc, rposix
 from rpython.rlib.rvmprof import cintf
 from rpython.rtyper.annlowlevel import cast_instance_to_gcref
 from rpython.rtyper.annlowlevel import cast_base_ptr_to_instance
 from rpython.rtyper.lltypesystem import rffi
 
-MAX_CODES = 8000 - 255
-MAX_FUNC_NAME = 255
+MAX_FUNC_NAME = 1023
 
 # ____________________________________________________________
 
@@ -34,8 +32,6 @@
 
     def _cleanup_(self):
         self.is_enabled = False
-        self.fileno = -1
-        self._current_codes = None
 
     @specialize.argtype(1)
     def register_code(self, code, full_name_func):
@@ -102,18 +98,13 @@
         assert fileno >= 0
         if self.is_enabled:
             raise VMProfError("vmprof is already enabled")
-        if not (1e-6 <= interval < 1.0):
-            raise VMProfError("bad value for 'interval'")
-        interval_usec = int(interval * 1000000.0)
 
-        p_error = self.cintf.vmprof_init(fileno)
+        p_error = self.cintf.vmprof_init(fileno, interval, "pypy")
         if p_error:
             raise VMProfError(rffi.charp2str(p_error))
 
-        self.fileno = fileno
-        self._write_header(interval_usec)
         self._gather_all_code_objs()
-        res = self.cintf.vmprof_enable(interval_usec)
+        res = self.cintf.vmprof_enable()
         if res < 0:
             raise VMProfError(os.strerror(rposix.get_saved_errno()))
         self.is_enabled = True
@@ -125,9 +116,6 @@
         if not self.is_enabled:
             raise VMProfError("vmprof is not enabled")
         self.is_enabled = False
-        if self._current_codes is not None:
-            self._flush_codes()
-        self.fileno = -1
         res = self.cintf.vmprof_disable()
         if res < 0:
             raise VMProfError(os.strerror(rposix.get_saved_errno()))
@@ -136,48 +124,8 @@
         assert name.count(':') == 3 and len(name) <= MAX_FUNC_NAME, (
             "the name must be 'class:func_name:func_line:filename' "
             "and at most %d characters; got '%s'" % (MAX_FUNC_NAME, name))
-        b = self._current_codes
-        if b is None:
-            b = self._current_codes = StringBuilder()
-        b.append('\x02')
-        _write_long_to_string_builder(uid, b)
-        _write_long_to_string_builder(len(name), b)
-        b.append(name)
-        if b.getlength() >= MAX_CODES:
-            self._flush_codes()
-
-    def _flush_codes(self):
-        buf = self._current_codes.build()
-        self._current_codes = None
-        self.cintf.vmprof_write_buf(buf, len(buf))
-        # NOTE: keep in mind that vmprof_write_buf() can only write
-        # a maximum of 8184 bytes.  This should be guaranteed here because:
-        assert MAX_CODES + 17 + MAX_FUNC_NAME <= 8184
-
-    def _write_header(self, interval_usec):
-        b = StringBuilder()
-        _write_long_to_string_builder(0, b)
-        _write_long_to_string_builder(3, b)
-        _write_long_to_string_builder(0, b)
-        _write_long_to_string_builder(interval_usec, b)
-        _write_long_to_string_builder(0, b)
-        b.append('\x04') # interp name
-        b.append(chr(len('pypy')))
-        b.append('pypy')
-        buf = b.build()
-        self.cintf.vmprof_write_buf(buf, len(buf))
-
-
-def _write_long_to_string_builder(l, b):
-    b.append(chr(l & 0xff))
-    b.append(chr((l >> 8) & 0xff))
-    b.append(chr((l >> 16) & 0xff))
-    b.append(chr((l >> 24) & 0xff))
-    if sys.maxint > 2147483647:
-        b.append(chr((l >> 32) & 0xff))
-        b.append(chr((l >> 40) & 0xff))
-        b.append(chr((l >> 48) & 0xff))
-        b.append(chr((l >> 56) & 0xff))
+        if self.cintf.vmprof_register_virtual_function(name, uid, 500000) < 0:
+            raise VMProfError("vmprof buffers full!  disk full or too slow")
 
 
 def vmprof_execute_code(name, get_code_fn, result_class=None):
diff --git a/rpython/rlib/rvmprof/src/rvmprof.c 
b/rpython/rlib/rvmprof/src/rvmprof.c
--- a/rpython/rlib/rvmprof/src/rvmprof.c
+++ b/rpython/rlib/rvmprof/src/rvmprof.c
@@ -1,22 +1,3 @@
-/* VMPROF
- *
- * statistical sampling profiler specifically designed to profile programs
- * which run on a Virtual Machine and/or bytecode interpreter, such as Python,
- * etc.
- *
- * The logic to dump the C stack traces is partly stolen from the code in
- * gperftools.
- * The file "getpc.h" has been entirely copied from gperftools.
- *
- * Tested only on gcc, linux, x86_64.
- *
- * Copyright (C) 2014-2015
- *   Antonio Cuni - anto.c...@gmail.com
- *   Maciej Fijalkowski - fij...@gmail.com
- *   Armin Rigo - ar...@tunes.org
- *
- */
-
 #define _GNU_SOURCE 1
 
 
@@ -39,431 +20,4 @@
 #endif
 
 
-#include <dlfcn.h>
-#include <assert.h>
-#include <pthread.h>
-#include <sys/time.h>
-#include <errno.h>
-#include <unistd.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include "rvmprof_getpc.h"
-#include "rvmprof_unwind.h"
-#include "rvmprof_mt.h"
-
-
-/************************************************************/
-
-// functions copied from libunwind using dlopen
-
-static int (*unw_get_reg)(unw_cursor_t*, int, unw_word_t*) = NULL;
-static int (*unw_step)(unw_cursor_t*) = NULL;
-static int (*unw_init_local)(unw_cursor_t *, unw_context_t *) = NULL;
-static int (*unw_get_proc_info)(unw_cursor_t *, unw_proc_info_t *) = NULL;
-
-static int profile_file = -1;
-
-
-RPY_EXTERN
-char *rpython_vmprof_init(int fd)
-{
-    if (!unw_get_reg) {
-        void *libhandle;
-
-        if (!(libhandle = dlopen("libunwind.so", RTLD_LAZY | RTLD_LOCAL)))
-            goto error;
-        if (!(unw_get_reg = dlsym(libhandle, "_ULx86_64_get_reg")))
-            goto error;
-        if (!(unw_get_proc_info = dlsym(libhandle, "_ULx86_64_get_proc_info")))
-            goto error;
-        if (!(unw_init_local = dlsym(libhandle, "_ULx86_64_init_local")))
-            goto error;
-        if (!(unw_step = dlsym(libhandle, "_ULx86_64_step")))
-            goto error;
-    }
-    if (prepare_concurrent_bufs() < 0)
-        return "out of memory";
-
-    assert(fd >= 0);
-    profile_file = fd;
-    return NULL;
-
- error:
-    return dlerror();
-}
-
-/************************************************************/
-
-/* value: last bit is 1 if signals must be ignored; all other bits
-   are a counter for how many threads are currently in a signal handler */
-static long volatile signal_handler_value = 1;
-
-RPY_EXTERN
-void rpython_vmprof_ignore_signals(int ignored)
-{
-    if (!ignored) {
-        __sync_fetch_and_and(&signal_handler_value, ~1L);
-    }
-    else {
-        /* set the last bit, and wait until concurrently-running signal
-           handlers finish */
-        while (__sync_or_and_fetch(&signal_handler_value, 1L) != 1L) {
-            usleep(1);
-        }
-    }
-}
-
-
-/* *************************************************************
- * functions to write a profile file compatible with gperftools
- * *************************************************************
- */
-
-#define MAX_FUNC_NAME 128
-#define MAX_STACK_DEPTH   \
-    ((SINGLE_BUF_SIZE - sizeof(struct prof_stacktrace_s)) / sizeof(void *))
-
-#define MARKER_STACKTRACE '\x01'
-#define MARKER_VIRTUAL_IP '\x02'
-#define MARKER_TRAILER '\x03'
-
-struct prof_stacktrace_s {
-    char padding[sizeof(long) - 1];
-    char marker;
-    long count, depth;
-    void *stack[];
-};
-
-static long profile_interval_usec = 0;
-static char atfork_hook_installed = 0;
-
-
-/* ******************************************************
- * libunwind workaround for process JIT frames correctly
- * ******************************************************
- */
-
-#include "rvmprof_get_custom_offset.h"
-
-typedef struct {
-    void* _unused1;
-    void* _unused2;
-    void* sp;
-    void* ip;
-    void* _unused3[sizeof(unw_cursor_t)/sizeof(void*) - 4];
-} vmprof_hacked_unw_cursor_t;
-
-static int vmprof_unw_step(unw_cursor_t *cp, int first_run)
-{
-    void* ip;
-    void* sp;
-    ptrdiff_t sp_offset;
-    unw_get_reg (cp, UNW_REG_IP, (unw_word_t*)&ip);
-    unw_get_reg (cp, UNW_REG_SP, (unw_word_t*)&sp);
-    if (!first_run) {
-        // make sure we're pointing to the CALL and not to the first
-        // instruction after. If the callee adjusts the stack for us
-        // it's not safe to be at the instruction after
-        ip -= 1;
-    }
-    sp_offset = vmprof_unw_get_custom_offset(ip, cp);
-
-    if (sp_offset == -1) {
-        // it means that the ip is NOT in JITted code, so we can use the
-        // stardard unw_step
-        return unw_step(cp);
-    }
-    else {
-        // this is a horrible hack to manually walk the stack frame, by
-        // setting the IP and SP in the cursor
-        vmprof_hacked_unw_cursor_t *cp2 = (vmprof_hacked_unw_cursor_t*)cp;
-        void* bp = (void*)sp + sp_offset;
-        cp2->sp = bp;
-        bp -= sizeof(void*);
-        cp2->ip = ((void**)bp)[0];
-        // the ret is on the top of the stack minus WORD
-        return 1;
-    }
-}
-
-
-/* *************************************************************
- * functions to dump the stack trace
- * *************************************************************
- */
-
-static int get_stack_trace(void** result, int max_depth, ucontext_t *ucontext)
-{
-    void *ip;
-    int n = 0;
-    unw_cursor_t cursor;
-    unw_context_t uc = *ucontext;
-
-    int ret = unw_init_local(&cursor, &uc);
-    assert(ret >= 0);
-    (void)ret;
-
-    while (n < max_depth) {
-        if (unw_get_reg(&cursor, UNW_REG_IP, (unw_word_t *) &ip) < 0) {
-            break;
-        }
-
-        unw_proc_info_t pip;
-        unw_get_proc_info(&cursor, &pip);
-
-        /* if n==0, it means that the signal handler interrupted us while we
-           were in the trampoline, so we are not executing (yet) the real main
-           loop function; just skip it */
-        if (VMPROF_ADDR_OF_TRAMPOLINE((void*)pip.start_ip) && n > 0) {
-            // found main loop stack frame
-            void* sp;
-            unw_get_reg(&cursor, UNW_REG_SP, (unw_word_t *) &sp);
-            void *arg_addr = (char*)sp /* + mainloop_sp_offset */;
-            void **arg_ptr = (void**)arg_addr;
-            /* if (mainloop_get_virtual_ip) {
-               ip = mainloop_get_virtual_ip(*arg_ptr);
-               } else { */
-            ip = *arg_ptr;
-        }
-
-        int first_run = (n == 0);
-        result[n++] = ip;
-        n = vmprof_write_header_for_jit_addr(result, n, ip, max_depth);
-        if (vmprof_unw_step(&cursor, first_run) <= 0)
-            break;
-    }
-    return n;
-}
-
-
-/* *************************************************************
- * the signal handler
- * *************************************************************
- */
-
-static void sigprof_handler(int sig_nr, siginfo_t* info, void *ucontext)
-{
-    long val = __sync_fetch_and_add(&signal_handler_value, 2L);
-
-    if ((val & 1) == 0) {
-        int saved_errno = errno;
-        int fd = profile_file;
-        assert(fd >= 0);
-
-        struct profbuf_s *p = reserve_buffer(fd);
-        if (p == NULL) {
-            /* ignore this signal: there are no free buffers right now */
-        }
-        else {
-            int depth;
-            struct prof_stacktrace_s *st = (struct prof_stacktrace_s *)p->data;
-            st->marker = MARKER_STACKTRACE;
-            st->count = 1;
-            st->stack[0] = GetPC((ucontext_t*)ucontext);
-            depth = get_stack_trace(st->stack+1, MAX_STACK_DEPTH-1, ucontext);
-            depth++;  // To account for pc value in stack[0];
-            st->depth = depth;
-            p->data_offset = offsetof(struct prof_stacktrace_s, marker);
-            p->data_size = (depth * sizeof(void *) +
-                            sizeof(struct prof_stacktrace_s) -
-                            offsetof(struct prof_stacktrace_s, marker));
-            commit_buffer(fd, p);
-        }
-
-        errno = saved_errno;
-    }
-
-    __sync_sub_and_fetch(&signal_handler_value, 2L);
-}
-
-
-/* *************************************************************
- * the setup and teardown functions
- * *************************************************************
- */
-
-static int install_sigprof_handler(void)
-{
-    struct sigaction sa;
-    memset(&sa, 0, sizeof(sa));
-    sa.sa_sigaction = sigprof_handler;
-    sa.sa_flags = SA_RESTART | SA_SIGINFO;
-    if (sigemptyset(&sa.sa_mask) == -1 ||
-        sigaction(SIGPROF, &sa, NULL) == -1)
-        return -1;
-    return 0;
-}
-
-static int remove_sigprof_handler(void)
-{
-    if (signal(SIGPROF, SIG_DFL) == SIG_ERR)
-        return -1;
-    return 0;
-}
-
-static int install_sigprof_timer(void)
-{
-    static struct itimerval timer;
-    timer.it_interval.tv_sec = 0;
-    timer.it_interval.tv_usec = profile_interval_usec;
-    timer.it_value = timer.it_interval;
-    if (setitimer(ITIMER_PROF, &timer, NULL) != 0)
-        return -1;
-    return 0;
-}
-
-static int remove_sigprof_timer(void) {
-    static struct itimerval timer;
-    timer.it_interval.tv_sec = 0;
-    timer.it_interval.tv_usec = 0;
-    timer.it_value.tv_sec = 0;
-    timer.it_value.tv_usec = 0;
-    if (setitimer(ITIMER_PROF, &timer, NULL) != 0)
-        return -1;
-    return 0;
-}
-
-static void atfork_disable_timer(void) {
-    if (profile_interval_usec > 0) {
-        remove_sigprof_timer();
-    }
-}
-
-static void atfork_enable_timer(void) {
-    if (profile_interval_usec > 0) {
-        install_sigprof_timer();
-    }
-}
-
-static int install_pthread_atfork_hooks(void) {
-    /* this is needed to prevent the problems described there:
-         - http://code.google.com/p/gperftools/issues/detail?id=278
-         - http://lists.debian.org/debian-glibc/2010/03/msg00161.html
-
-        TL;DR: if the RSS of the process is large enough, the clone() syscall
-        will be interrupted by the SIGPROF before it can complete, then
-        retried, interrupted again and so on, in an endless loop.  The
-        solution is to disable the timer around the fork, and re-enable it
-        only inside the parent.
-    */
-    if (atfork_hook_installed)
-        return 0;
-    int ret = pthread_atfork(atfork_disable_timer, atfork_enable_timer, NULL);
-    if (ret != 0)
-        return -1;
-    atfork_hook_installed = 1;
-    return 0;
-}
-
-RPY_EXTERN
-int rpython_vmprof_enable(long interval_usec)
-{
-    assert(profile_file >= 0);
-    assert(interval_usec > 0);
-    profile_interval_usec = interval_usec;
-
-    if (install_pthread_atfork_hooks() == -1)
-        goto error;
-    if (install_sigprof_handler() == -1)
-        goto error;
-    if (install_sigprof_timer() == -1)
-        goto error;
-    rpython_vmprof_ignore_signals(0);
-    return 0;
-
- error:
-    profile_file = -1;
-    profile_interval_usec = 0;
-    return -1;
-}
-
-static int _write_all(const void *buf, size_t bufsize)
-{
-    while (bufsize > 0) {
-        ssize_t count = write(profile_file, buf, bufsize);
-        if (count <= 0)
-            return -1;   /* failed */
-        buf += count;
-        bufsize -= count;
-    }
-    return 0;
-}
-
-static int close_profile(void)
-{
-    char buf[4096];
-    ssize_t size;
-    unsigned char marker = MARKER_TRAILER;
-
-    if (_write_all(&marker, 1) < 0)
-        return -1;
-
-#ifdef __linux__
-    // copy /proc/self/maps to the end of the profile file
-    int srcfd = open("/proc/self/maps", O_RDONLY);
-    if (srcfd < 0)
-        return -1;
-
-    while ((size = read(srcfd, buf, sizeof buf)) > 0) {
-        if (_write_all(buf, size) < 0) {
-            close(srcfd);
-            return -1;
-        }
-    }
-    close(srcfd);
-#else
-    // freebsd and mac
-    sprintf(buf, "procstat -v %d", getpid());
-    FILE *srcf = popen(buf, "r");
-    if (!srcf)
-        return -1;
-
-    while ((size = fread(buf, 1, sizeof buf, src))) {
-        if (_write_all(buf, size) < 0) {
-            pclose(srcf);
-            return -1;
-        }
-    }
-    pclose(srcf);
-#endif
-
-    /* don't close() the file descriptor from here */
-    profile_file = -1;
-    return 0;
-}
-
-RPY_EXTERN
-int rpython_vmprof_disable(void)
-{
-    rpython_vmprof_ignore_signals(1);
-    profile_interval_usec = 0;
-
-    if (remove_sigprof_timer() == -1)
-        return -1;
-    if (remove_sigprof_handler() == -1)
-        return -1;
-    if (shutdown_concurrent_bufs(profile_file) < 0)
-        return -1;
-    return close_profile();
-}
-
-RPY_EXTERN
-void rpython_vmprof_write_buf(char *buf, long size)
-{
-    struct profbuf_s *p;
-
-    while ((p = reserve_buffer(profile_file)) == NULL) {
-        /* spin loop waiting for a buffer to be ready; should almost never
-           be the case */
-        usleep(1);
-    }
-
-    if (size > SINGLE_BUF_SIZE)
-        size = SINGLE_BUF_SIZE;
-    memcpy(p->data, buf, size);
-    p->data_size = size;
-
-    commit_buffer(profile_file, p);
-}
+#include "vmprof_main.h"
diff --git a/rpython/rlib/rvmprof/src/rvmprof.h 
b/rpython/rlib/rvmprof/src/rvmprof.h
--- a/rpython/rlib/rvmprof/src/rvmprof.h
+++ b/rpython/rlib/rvmprof/src/rvmprof.h
@@ -1,6 +1,6 @@
 
-RPY_EXTERN char *rpython_vmprof_init(int);
-RPY_EXTERN void rpython_vmprof_ignore_signals(int);
-RPY_EXTERN int rpython_vmprof_enable(long);
-RPY_EXTERN int rpython_vmprof_disable(void);
-RPY_EXTERN void rpython_vmprof_write_buf(char *, long);
+RPY_EXTERN char *vmprof_init(int, double, char *);
+RPY_EXTERN void vmprof_ignore_signals(int);
+RPY_EXTERN int vmprof_enable(void);
+RPY_EXTERN int vmprof_disable(void);
+RPY_EXTERN int vmprof_register_virtual_function(char *, long, int);
diff --git a/rpython/rlib/rvmprof/src/rvmprof_get_custom_offset.h 
b/rpython/rlib/rvmprof/src/rvmprof_get_custom_offset.h
deleted file mode 100644
--- a/rpython/rlib/rvmprof/src/rvmprof_get_custom_offset.h
+++ /dev/null
@@ -1,63 +0,0 @@
-
-#ifdef PYPY_JIT_CODEMAP
-void *pypy_find_codemap_at_addr(long addr, long *start_addr);
-long pypy_yield_codemap_at_addr(void *codemap_raw, long addr,
-                                long *current_pos_addr);
-long pypy_jit_stack_depth_at_loc(long loc);
-#endif
-
-
-static ptrdiff_t vmprof_unw_get_custom_offset(void* ip, void *cp) {
-#ifdef PYPY_JIT_CODEMAP
-    intptr_t ip_l = (intptr_t)ip;
-    return pypy_jit_stack_depth_at_loc(ip_l);
-#else
-    return -1;
-#endif
-}
-
-static long vmprof_write_header_for_jit_addr(void **result, long n,
-                                             void *ip, int max_depth)
-{
-#ifdef PYPY_JIT_CODEMAP
-    void *codemap;
-    long current_pos = 0;
-    intptr_t id;
-    long start_addr = 0;
-    intptr_t addr = (intptr_t)ip;
-    int start, k;
-    void *tmp;
-
-    codemap = pypy_find_codemap_at_addr(addr, &start_addr);
-    if (codemap == NULL)
-        // not a jit code at all
-        return n;
-
-    // modify the last entry to point to start address and not the random one
-    // in the middle
-    result[n - 1] = (void*)start_addr;
-    result[n] = (void*)2;
-    n++;
-    start = n;
-    while (n < max_depth) {
-        id = pypy_yield_codemap_at_addr(codemap, addr, &current_pos);
-        if (id == -1)
-            // finish
-            break;
-        if (id == 0)
-            continue; // not main codemap
-        result[n++] = (void *)id;
-    }
-    k = 0;
-    while (k < (n - start) / 2) {
-        tmp = result[start + k];
-        result[start + k] = result[n - k - 1];
-        result[n - k - 1] = tmp;
-        k++;
-    }
-    if (n < max_depth) {
-        result[n++] = (void*)3;
-    }
-#endif
-    return n;
-}
diff --git a/rpython/rlib/rvmprof/src/rvmprof_getpc.h 
b/rpython/rlib/rvmprof/src/rvmprof_getpc.h
deleted file mode 100644
--- a/rpython/rlib/rvmprof/src/rvmprof_getpc.h
+++ /dev/null
@@ -1,187 +0,0 @@
-// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
-// Copyright (c) 2005, Google Inc.
-// All rights reserved.
-//
-// Redistribution and use in source and binary forms, with or without
-// modification, are permitted provided that the following conditions are
-// met:
-//
-//     * Redistributions of source code must retain the above copyright
-// notice, this list of conditions and the following disclaimer.
-//     * Redistributions in binary form must reproduce the above
-// copyright notice, this list of conditions and the following disclaimer
-// in the documentation and/or other materials provided with the
-// distribution.
-//     * Neither the name of Google Inc. nor the names of its
-// contributors may be used to endorse or promote products derived from
-// this software without specific prior written permission.
-//
-// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
-// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
-// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
-// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
-// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
-// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
-// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
-// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-
-// ---
-// Author: Craig Silverstein
-//
-// This is an internal header file used by profiler.cc.  It defines
-// the single (inline) function GetPC.  GetPC is used in a signal
-// handler to figure out the instruction that was being executed when
-// the signal-handler was triggered.
-//
-// To get this, we use the ucontext_t argument to the signal-handler
-// callback, which holds the full context of what was going on when
-// the signal triggered.  How to get from a ucontext_t to a Program
-// Counter is OS-dependent.
-
-#ifndef BASE_GETPC_H_
-#define BASE_GETPC_H_
-
-#include "rvmprof_config.h"
-
-// On many linux systems, we may need _GNU_SOURCE to get access to
-// the defined constants that define the register we want to see (eg
-// REG_EIP).  Note this #define must come first!
-#define _GNU_SOURCE 1
-// If #define _GNU_SOURCE causes problems, this might work instead.
-// It will cause problems for FreeBSD though!, because it turns off
-// the needed __BSD_VISIBLE.
-//#define _XOPEN_SOURCE 500
-
-#include <string.h>         // for memcmp
-#if defined(HAVE_SYS_UCONTEXT_H)
-#include <sys/ucontext.h>
-#elif defined(HAVE_UCONTEXT_H)
-#include <ucontext.h>       // for ucontext_t (and also mcontext_t)
-#elif defined(HAVE_CYGWIN_SIGNAL_H)
-#include <cygwin/signal.h>
-typedef ucontext ucontext_t;
-#endif
-
-
-// Take the example where function Foo() calls function Bar().  For
-// many architectures, Bar() is responsible for setting up and tearing
-// down its own stack frame.  In that case, it's possible for the
-// interrupt to happen when execution is in Bar(), but the stack frame
-// is not properly set up (either before it's done being set up, or
-// after it's been torn down but before Bar() returns).  In those
-// cases, the stack trace cannot see the caller function anymore.
-//
-// GetPC can try to identify this situation, on architectures where it
-// might occur, and unwind the current function call in that case to
-// avoid false edges in the profile graph (that is, edges that appear
-// to show a call skipping over a function).  To do this, we hard-code
-// in the asm instructions we might see when setting up or tearing
-// down a stack frame.
-//
-// This is difficult to get right: the instructions depend on the
-// processor, the compiler ABI, and even the optimization level.  This
-// is a best effort patch -- if we fail to detect such a situation, or
-// mess up the PC, nothing happens; the returned PC is not used for
-// any further processing.
-struct CallUnrollInfo {
-  // Offset from (e)ip register where this instruction sequence
-  // should be matched. Interpreted as bytes. Offset 0 is the next
-  // instruction to execute. Be extra careful with negative offsets in
-  // architectures of variable instruction length (like x86) - it is
-  // not that easy as taking an offset to step one instruction back!
-  int pc_offset;
-  // The actual instruction bytes. Feel free to make it larger if you
-  // need a longer sequence.
-  unsigned char ins[16];
-  // How many bytes to match from ins array?
-  int ins_size;
-  // The offset from the stack pointer (e)sp where to look for the
-  // call return address. Interpreted as bytes.
-  int return_sp_offset;
-};
-
-
-// The dereferences needed to get the PC from a struct ucontext were
-// determined at configure time, and stored in the macro
-// PC_FROM_UCONTEXT in config.h.  The only thing we need to do here,
-// then, is to do the magic call-unrolling for systems that support it.
-
-// -- Special case 1: linux x86, for which we have CallUnrollInfo
-#if defined(__linux) && defined(__i386) && defined(__GNUC__)
-static const CallUnrollInfo callunrollinfo[] = {
-  // Entry to a function:  push %ebp;  mov  %esp,%ebp
-  // Top-of-stack contains the caller IP.
-  { 0,
-    {0x55, 0x89, 0xe5}, 3,
-    0
-  },
-  // Entry to a function, second instruction:  push %ebp;  mov  %esp,%ebp
-  // Top-of-stack contains the old frame, caller IP is +4.
-  { -1,
-    {0x55, 0x89, 0xe5}, 3,
-    4
-  },
-  // Return from a function: RET.
-  // Top-of-stack contains the caller IP.
-  { 0,
-    {0xc3}, 1,
-    0
-  }
-};
-
-void* GetPC(ucontext_t *signal_ucontext) {
-  // See comment above struct CallUnrollInfo.  Only try instruction
-  // flow matching if both eip and esp looks reasonable.
-  const int eip = signal_ucontext->uc_mcontext.gregs[REG_EIP];
-  const int esp = signal_ucontext->uc_mcontext.gregs[REG_ESP];
-  if ((eip & 0xffff0000) != 0 && (~eip & 0xffff0000) != 0 &&
-      (esp & 0xffff0000) != 0) {
-    char* eip_char = reinterpret_cast<char*>(eip);
-    for (int i = 0; i < sizeof(callunrollinfo)/sizeof(*callunrollinfo); ++i) {
-      if (!memcmp(eip_char + callunrollinfo[i].pc_offset,
-                  callunrollinfo[i].ins, callunrollinfo[i].ins_size)) {
-        // We have a match.
-        void **retaddr = (void**)(esp + callunrollinfo[i].return_sp_offset);
-        return *retaddr;
-      }
-    }
-  }
-  return (void*)eip;
-}
-
-// Special case #2: Windows, which has to do something totally different.
-#elif defined(_WIN32) || defined(__CYGWIN__) || defined(__CYGWIN32__) || 
defined(__MINGW32__)
-// If this is ever implemented, probably the way to do it is to have
-// profiler.cc use a high-precision timer via timeSetEvent:
-//    http://msdn2.microsoft.com/en-us/library/ms712713.aspx
-// We'd use it in mode TIME_CALLBACK_FUNCTION/TIME_PERIODIC.
-// The callback function would be something like prof_handler, but
-// alas the arguments are different: no ucontext_t!  I don't know
-// how we'd get the PC (using StackWalk64?)
-//    http://msdn2.microsoft.com/en-us/library/ms680650.aspx
-
-#include "base/logging.h"   // for RAW_LOG
-#ifndef HAVE_CYGWIN_SIGNAL_H
-typedef int ucontext_t;
-#endif
-
-void* GetPC(ucontext_t *signal_ucontext) {
-  RAW_LOG(ERROR, "GetPC is not yet implemented on Windows\n");
-  return NULL;
-}
-
-// Normal cases.  If this doesn't compile, it's probably because
-// PC_FROM_UCONTEXT is the empty string.  You need to figure out
-// the right value for your system, and add it to the list in
-// configure.ac (or set it manually in your config.h).
-#else
-void* GetPC(ucontext_t *signal_ucontext) {
-  return (void*)signal_ucontext->PC_FROM_UCONTEXT;   // defined in config.h
-}
-
-#endif
-
-#endif  // BASE_GETPC_H_
diff --git a/rpython/rlib/rvmprof/src/rvmprof_mt.h 
b/rpython/rlib/rvmprof/src/rvmprof_mt.h
deleted file mode 100644
--- a/rpython/rlib/rvmprof/src/rvmprof_mt.h
+++ /dev/null
@@ -1,210 +0,0 @@
-/* Support for multithreaded write() operations */
-
-#include <sys/mman.h>
-#include <string.h>
-
-/* The idea is that we have MAX_NUM_BUFFERS available, all of size
-   SINGLE_BUF_SIZE.  Threads and signal handlers can ask to reserve a
-   buffer, fill it, and finally "commit" it, at which point its
-   content is written into the profile file.  There is no hard
-   guarantee about the order in which the committed blocks are
-   actually written.  We do this with two constrains:
-
-   - write() calls should not overlap; only one thread can be
-     currently calling it.
-
-   - the code needs to be multithread-safe *and* signal-handler-safe,
-     which means it must be written in a wait-free style: never have
-     spin loops waiting for some lock to be released, from any of
-     the functions that can be called from the signal handler!  The
-     code holding the lock could be running in the same thread,
-     currently interrupted by the signal handler.
-
-   The value of MAX_NUM_BUFFERS is a trade-off between too high
-   (lots of unnecessary memory, lots of checking all of them)
-   and too low (risk that there is none left).
-*/
-#define MAX_NUM_BUFFERS  20
-#define SINGLE_BUF_SIZE  (8192 - 2 * sizeof(unsigned int))
-
-#if defined(__i386__) || defined(__amd64__)
-  static inline void write_fence(void) { asm("" : : : "memory"); }
-#else
-  static inline void write_fence(void) { __sync_synchronize(); }
-#endif
-
-
-#define PROFBUF_UNUSED   0
-#define PROFBUF_FILLING  1
-#define PROFBUF_READY    2
-
-
-struct profbuf_s {
-    unsigned int data_size;
-    unsigned int data_offset;
-    char data[SINGLE_BUF_SIZE];
-};
-
-static char volatile profbuf_state[MAX_NUM_BUFFERS];
-static struct profbuf_s *profbuf_all_buffers = NULL;
-static int volatile profbuf_write_lock = 2;
-static long profbuf_pending_write;
-
-
-static void unprepare_concurrent_bufs(void)
-{
-    if (profbuf_all_buffers != NULL) {
-        munmap(profbuf_all_buffers, sizeof(struct profbuf_s) * 
MAX_NUM_BUFFERS);
-        profbuf_all_buffers = NULL;
-    }
-}
-
-static int prepare_concurrent_bufs(void)
-{
-    assert(sizeof(struct profbuf_s) == 8192);
-
-    unprepare_concurrent_bufs();
-    profbuf_all_buffers = mmap(NULL, sizeof(struct profbuf_s) * 
MAX_NUM_BUFFERS,
-                               PROT_READ | PROT_WRITE,
-                               MAP_PRIVATE | MAP_ANONYMOUS,
-                               -1, 0);
-    if (profbuf_all_buffers == MAP_FAILED) {
-        profbuf_all_buffers = NULL;
-        return -1;
-    }
-    memset((char *)profbuf_state, PROFBUF_UNUSED, sizeof(profbuf_state));
-    profbuf_write_lock = 0;
-    profbuf_pending_write = -1;
-    return 0;
-}
-
-static int _write_single_ready_buffer(int fd, long i)
-{
-    /* Try to write to disk the buffer number 'i'.  This function must
-       only be called while we hold the write lock. */
-    assert(profbuf_write_lock != 0);
-
-    if (profbuf_pending_write >= 0) {
-        /* A partially written buffer is waiting.  We'll write the
-           rest of this buffer now, instead of 'i'. */
-        i = profbuf_pending_write;
-        assert(profbuf_state[i] == PROFBUF_READY);
-    }
-
-    if (profbuf_state[i] != PROFBUF_READY) {
-        /* this used to be a race condition: the buffer was written by a
-           different thread already, nothing to do now */
-        return 0;
-    }
-
-    int err;
-    struct profbuf_s *p = &profbuf_all_buffers[i];
-    ssize_t count = write(fd, p->data + p->data_offset, p->data_size);
-    if (count == p->data_size) {
-        profbuf_state[i] = PROFBUF_UNUSED;
-        profbuf_pending_write = -1;
-    }
-    else {
-        if (count > 0) {
-            p->data_offset += count;
-            p->data_size -= count;
-        }
-        profbuf_pending_write = i;
-        if (count < 0)
-            return -1;
-    }
-    return 0;
-}
-
-static void _write_ready_buffers(int fd)
-{
-    long i;
-    int has_write_lock = 0;
-
-    for (i = 0; i < MAX_NUM_BUFFERS; i++) {
-        if (profbuf_state[i] == PROFBUF_READY) {
-            if (!has_write_lock) {
-                if (!__sync_bool_compare_and_swap(&profbuf_write_lock, 0, 1))
-                    return;   /* can't acquire the write lock, give up */
-                has_write_lock = 1;
-            }
-            if (_write_single_ready_buffer(fd, i) < 0)
-                break;
-        }
-    }
-    if (has_write_lock)
-        profbuf_write_lock = 0;
-}
-
-static struct profbuf_s *reserve_buffer(int fd)
-{
-    /* Tries to enter a region of code that fills one buffer.  If
-       successful, returns the profbuf_s.  It fails only if the
-       concurrent buffers are all busy (extreme multithreaded usage).
-
-       This might call write() to emit the data sitting in
-       previously-prepared buffers.  In case of write() error, the
-       error is ignored but unwritten data stays in the buffers.
-    */
-    long i;
-
-    _write_ready_buffers(fd);
-
-    for (i = 0; i < MAX_NUM_BUFFERS; i++) {
-        if (profbuf_state[i] == PROFBUF_UNUSED &&
-            __sync_bool_compare_and_swap(&profbuf_state[i], PROFBUF_UNUSED,
-                                         PROFBUF_FILLING)) {
-            struct profbuf_s *p = &profbuf_all_buffers[i];
-            p->data_size = 0;
-            p->data_offset = 0;
-            return p;
-        }
-    }
-    /* no unused buffer found */
-    return NULL;
-}
-
-static void commit_buffer(int fd, struct profbuf_s *buf)
-{
-    /* Leaves a region of code that filled 'buf'.
-
-       This might call write() to emit the data now ready.  In case of
-       write() error, the error is ignored but unwritten data stays in
-       the buffers.
-    */
-
-    /* Make sure every thread sees the full content of 'buf' */
-    write_fence();
-
-    /* Then set the 'ready' flag */
-    long i = buf - profbuf_all_buffers;
-    assert(profbuf_state[i] == PROFBUF_FILLING);
-    profbuf_state[i] = PROFBUF_READY;
-
-    if (!__sync_bool_compare_and_swap(&profbuf_write_lock, 0, 1)) {
-        /* can't acquire the write lock, ignore */
-    }
-    else {
-        _write_single_ready_buffer(fd, i);
-        profbuf_write_lock = 0;
-    }
-}
-
-static int shutdown_concurrent_bufs(int fd)
-{
-    /* no signal handler can be running concurrently here, because we
-       already did rpython_vmprof_ignore_signals(1) */
-    assert(profbuf_write_lock == 0);
-    profbuf_write_lock = 2;
-
-    /* last attempt to flush buffers */
-    int i;
-    for (i = 0; i < MAX_NUM_BUFFERS; i++) {
-        while (profbuf_state[i] == PROFBUF_READY) {
-            if (_write_single_ready_buffer(fd, i) < 0)
-                return -1;
-        }
-    }
-    unprepare_concurrent_bufs();
-    return 0;
-}
diff --git a/rpython/rlib/rvmprof/src/rvmprof_config.h 
b/rpython/rlib/rvmprof/src/vmprof_config.h
rename from rpython/rlib/rvmprof/src/rvmprof_config.h
rename to rpython/rlib/rvmprof/src/vmprof_config.h
diff --git a/rpython/rlib/rvmprof/src/vmprof_get_custom_offset.h 
b/rpython/rlib/rvmprof/src/vmprof_get_custom_offset.h
new file mode 100644
--- /dev/null
+++ b/rpython/rlib/rvmprof/src/vmprof_get_custom_offset.h
@@ -0,0 +1,120 @@
+
+#ifdef PYPY_JIT_CODEMAP
+void *pypy_find_codemap_at_addr(long addr, long *start_addr);
+long pypy_yield_codemap_at_addr(void *codemap_raw, long addr,
+                                long *current_pos_addr);
+long pypy_jit_stack_depth_at_loc(long loc);
+#endif
+
+
+#ifdef CPYTHON_GET_CUSTOM_OFFSET
+static void *tramp_start, *tramp_end;
+#endif
+
+
+static ptrdiff_t vmprof_unw_get_custom_offset(void* ip, void *cp) {
+
+#if defined(PYPY_JIT_CODEMAP)
+
+    intptr_t ip_l = (intptr_t)ip;
+    return pypy_jit_stack_depth_at_loc(ip_l);
+
+#elif defined(CPYTHON_GET_CUSTOM_OFFSET)
+
+    if (ip >= tramp_start && ip <= tramp_end) {
+        // XXX the return value is wrong for all the places before push and
+        //     after pop, fix
+        void *bp;
+        void *sp;
+
+        /* This is a stage2 trampoline created by hotpatch:
+
+               push   %rbx
+               push   %rbp
+               mov    %rsp,%rbp
+               and    $0xfffffffffffffff0,%rsp   // make sure the stack is 
aligned
+               movabs $0x7ffff687bb10,%rbx
+               callq  *%rbx
+               leaveq 
+               pop    %rbx
+               retq   
+
+           the stack layout is like this:
+
+               +-----------+                      high addresses
+               | ret addr  |
+               +-----------+
+               | saved rbx |   start of the function frame
+               +-----------+
+               | saved rbp |
+               +-----------+
+               | ........  |   <-- rbp
+               +-----------+                      low addresses
+
+           So, the trampoline frame starts at rbp+16, and the return address,
+           is at rbp+24.  The vmprof API requires us to return the offset of
+           the frame relative to sp, hence we have this weird computation.
+
+           XXX (antocuni): I think we could change the API to return directly
+           the frame address instead of the offset; however, this require a
+           change in the PyPy code too
+        */
+
+        unw_get_reg (cp, UNW_REG_SP, (unw_word_t*)&sp);
+        unw_get_reg (cp, UNW_X86_64_RBP, (unw_word_t*)&bp);
+        return bp+16+8-sp;
+    }
+    return -1;
+
+#else
+
+    return -1;
+
+#endif
+}
+
+static long vmprof_write_header_for_jit_addr(void **result, long n,
+                                             void *ip, int max_depth)
+{
+#ifdef PYPY_JIT_CODEMAP
+    void *codemap;
+    long current_pos = 0;
+    intptr_t id;
+    long start_addr = 0;
+    intptr_t addr = (intptr_t)ip;
+    int start, k;
+    void *tmp;
+
+    codemap = pypy_find_codemap_at_addr(addr, &start_addr);
+    if (codemap == NULL)
+        // not a jit code at all
+        return n;
+
+    // modify the last entry to point to start address and not the random one
+    // in the middle
+    result[n - 1] = (void*)start_addr;
+    result[n] = (void*)2;
+    n++;
+    start = n;
+    while (n < max_depth) {
+        id = pypy_yield_codemap_at_addr(codemap, addr, &current_pos);
+        if (id == -1)
+            // finish
+            break;
+        if (id == 0)
+            continue; // not main codemap
+        result[n++] = (void *)id;
+    }
+    k = 0;
+    while (k < (n - start) / 2) {
+        tmp = result[start + k];
+        result[start + k] = result[n - k - 1];
+        result[n - k - 1] = tmp;
+        k++;
+    }
+    if (n < max_depth) {
+        result[n++] = (void*)3;
+    }
+#endif
+    return n;
+}
diff --git a/rpython/rlib/rvmprof/src/vmprof_getpc.h 
b/rpython/rlib/rvmprof/src/vmprof_getpc.h
new file mode 100644
--- /dev/null
+++ b/rpython/rlib/rvmprof/src/vmprof_getpc.h
@@ -0,0 +1,193 @@
+// -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil -*-
+// Copyright (c) 2005, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+//     * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+//     * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+//     * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to