[pypy-commit] pypy py3.5: hg merge default

rlamy pypy.commits at gmail.com
Mon Nov 20 20:59:53 EST 2017


Author: Ronan Lamy <ronan.lamy at gmail.com>
Branch: py3.5
Changeset: r93107:3e868c28555c
Date: 2017-11-21 01:59 +0000
http://bitbucket.org/pypy/pypy/changeset/3e868c28555c/

Log:	hg merge default

diff --git a/lib-python/2.7/test/test_urllib2net.py b/lib-python/2.7/test/test_urllib2net.py
--- a/lib-python/2.7/test/test_urllib2net.py
+++ b/lib-python/2.7/test/test_urllib2net.py
@@ -286,7 +286,7 @@
             self.assertEqual(u.fp._sock.fp._sock.gettimeout(), 120)
             u.close()
 
-    FTP_HOST = 'ftp://ftp.debian.org/debian/'
+    FTP_HOST = 'ftp://www.pythontest.net/'
 
     def test_ftp_basic(self):
         self.assertIsNone(socket.getdefaulttimeout())
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
@@ -20,3 +20,9 @@
 
 .. branch: run-extra-tests
 Run extra_tests/ in buildbot
+
+.. branch: vmprof-0.4.10
+Upgrade the _vmprof backend to vmprof 0.4.10
+
+.. branch: fix-vmprof-stacklet-switch
+Fix a vmprof+continulets (i.e. greenelts, eventlet, gevent, ...)
diff --git a/pypy/module/_continuation/test/test_stacklet.py b/pypy/module/_continuation/test/test_stacklet.py
--- a/pypy/module/_continuation/test/test_stacklet.py
+++ b/pypy/module/_continuation/test/test_stacklet.py
@@ -8,6 +8,35 @@
         cls.w_translated = cls.space.wrap(
             os.path.join(os.path.dirname(__file__),
                          'test_translated.py'))
+        cls.w_stack = cls.space.appexec([], """():
+            import sys
+            def stack(f=None):
+                '''
+                get the call-stack of the caller or the specified frame
+                '''
+                if f is None:
+                    f = sys._getframe(1)
+                res = []
+                seen = set()
+                while f:
+                    if f in seen:
+                        # frame cycle
+                        res.append('...')
+                        break
+                    if f.f_code.co_name == 'runtest':
+                        # if we are running with -A, cut all the stack above
+                        # the test function
+                        break
+                    seen.add(f)
+                    res.append(f.f_code.co_name)
+                    f = f.f_back
+                #print res
+                return res
+            return stack
+       """)
+        if cls.runappdirect:
+            # make sure that "self.stack" does not pass the self
+            cls.w_stack = staticmethod(cls.w_stack.im_func)
 
     def test_new_empty(self):
         from _continuation import continulet
@@ -339,17 +368,24 @@
     def test_f_back(self):
         import sys
         from _continuation import continulet
+        stack = self.stack
         #
         def bar(c):
+            assert stack() == ['bar', 'foo', 'test_f_back']
             c.switch(sys._getframe(0))
             c.switch(sys._getframe(0).f_back)
             c.switch(sys._getframe(1))
+            #
+            assert stack() == ['bar', 'foo', 'main', 'test_f_back']
             c.switch(sys._getframe(1).f_back)
+            #
+            assert stack() == ['bar', 'foo', 'main2', 'test_f_back']
             assert sys._getframe(2) is f3_foo.f_back
             c.switch(sys._getframe(2))
         def foo(c):
             bar(c)
         #
+        assert stack() == ['test_f_back']
         c = continulet(foo)
         f1_bar = c.switch()
         assert f1_bar.f_code.co_name == 'bar'
@@ -358,14 +394,20 @@
         f3_foo = c.switch()
         assert f3_foo is f2_foo
         assert f1_bar.f_back is f3_foo
+        #
         def main():
             f4_main = c.switch()
             assert f4_main.f_code.co_name == 'main'
             assert f3_foo.f_back is f1_bar    # not running, so a loop
+            assert stack() == ['main', 'test_f_back']
+            assert stack(f1_bar) == ['bar', 'foo', '...']
+        #
         def main2():
             f5_main2 = c.switch()
             assert f5_main2.f_code.co_name == 'main2'
             assert f3_foo.f_back is f1_bar    # not running, so a loop
+            assert stack(f1_bar) == ['bar', 'foo', '...']
+        #
         main()
         main2()
         res = c.switch()
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
@@ -5,6 +5,7 @@
     py.test.skip("to run on top of a translated pypy-c")
 
 import sys, random
+from rpython.tool.udir import udir
 
 # ____________________________________________________________
 
@@ -92,6 +93,33 @@
         from pypy.conftest import option
         if not option.runappdirect:
             py.test.skip("meant only for -A run")
+        cls.w_vmprof_file = cls.space.wrap(str(udir.join('profile.vmprof')))
+
+    def test_vmprof(self):
+        """
+        The point of this test is to check that we do NOT segfault.  In
+        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")
+        #
+        def switch_forever(c):
+            while True:
+                c.switch()
+        #
+        f = open(self.vmprof_file, 'w+b')
+        _vmprof.enable(f.fileno(), 1/250.0, False, False, False, False)
+        c = _continuation.continulet(switch_forever)
+        for i in range(10**7):
+            if i % 100000 == 0:
+                print i
+            c.switch()
+        _vmprof.disable()
+        f.close()
+
 
 def _setup():
     for _i in range(20):
diff --git a/pypy/module/_vmprof/interp_vmprof.py b/pypy/module/_vmprof/interp_vmprof.py
--- a/pypy/module/_vmprof/interp_vmprof.py
+++ b/pypy/module/_vmprof/interp_vmprof.py
@@ -93,8 +93,8 @@
     return space.newtext(path)
 
 def stop_sampling(space):
-    return space.newint(rvmprof.stop_sampling(space))
+    return space.newint(rvmprof.stop_sampling())
 
 def start_sampling(space):
-    rvmprof.start_sampling(space)
+    rvmprof.start_sampling()
     return space.w_None
diff --git a/pypy/module/cpyext/longobject.py b/pypy/module/cpyext/longobject.py
--- a/pypy/module/cpyext/longobject.py
+++ b/pypy/module/cpyext/longobject.py
@@ -237,9 +237,9 @@
     assert isinstance(w_long, W_LongObject)
     return w_long.num.sign
 
-UCHARP = lltype.Ptr(lltype.Array(
-    rffi.UCHAR, hints={'nolength':True, 'render_as_const':True}))
- at cpython_api([UCHARP, rffi.SIZE_T, rffi.INT_real, rffi.INT_real], PyObject)
+CONST_UCHARP = lltype.Ptr(lltype.Array(rffi.UCHAR, hints={'nolength': True,
+                                       'render_as_const': True}))
+ at cpython_api([CONST_UCHARP, rffi.SIZE_T, rffi.INT_real, rffi.INT_real], PyObject)
 def _PyLong_FromByteArray(space, bytes, n, little_endian, signed):
     little_endian = rffi.cast(lltype.Signed, little_endian)
     signed = rffi.cast(lltype.Signed, signed)
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
@@ -2271,7 +2271,7 @@
         char32_t foo_4bytes(char32_t);
     """)
     lib = verify(ffi, "test_char16_char32_type" + no_cpp * "_nocpp", """
-    #if !defined(__cplusplus) || __cplusplus < 201103L
+    #if !defined(__cplusplus) || (!defined(_LIBCPP_VERSION) && __cplusplus < 201103L)
     typedef uint_least16_t char16_t;
     typedef uint_least32_t char32_t;
     #endif
diff --git a/pypy/module/thread/test/test_import_lock.py b/pypy/module/thread/test/test_import_lock.py
--- a/pypy/module/thread/test/test_import_lock.py
+++ b/pypy/module/thread/test/test_import_lock.py
@@ -101,8 +101,8 @@
         importhook(space, 'sys')
         assert importlock.count == 0
         # A new module
-        importhook(space, "time")
-        assert importlock.count == 1
+        importhook(space, 're')
+        assert importlock.count >= 9
         # Import it again
         previous_count = importlock.count
         importhook(space, "time")
diff --git a/rpython/annotator/annrpython.py b/rpython/annotator/annrpython.py
--- a/rpython/annotator/annrpython.py
+++ b/rpython/annotator/annrpython.py
@@ -15,34 +15,10 @@
     typeof, s_ImpossibleValue, SomeInstance, intersection, difference)
 from rpython.annotator.bookkeeper import Bookkeeper
 from rpython.rtyper.normalizecalls import perform_normalizations
-from collections import deque
 
 log = AnsiLogger("annrpython")
 
 
-class ShuffleDict(object):
-    def __init__(self):
-        self._d = {}
-        self.keys = deque()
-
-    def __setitem__(self, k, v):
-        if k in self._d:
-            self._d[k] = v
-        else:
-            self._d[k] = v
-            self.keys.append(k)
-
-    def __getitem__(self, k):
-        return self._d[k]
-
-    def popitem(self):
-        key = self.keys.popleft()
-        item = self._d.pop(key)
-        return (key, item)
-
-    def __nonzero__(self):
-        return bool(self._d)
-
 class RPythonAnnotator(object):
     """Block annotator for RPython.
     See description in doc/translation.txt."""
@@ -57,7 +33,7 @@
             translator = TranslationContext()
             translator.annotator = self
         self.translator = translator
-        self.pendingblocks = ShuffleDict()  # map {block: graph-containing-it}
+        self.genpendingblocks=[{}] # [{block: graph-containing-it}] * generation
         self.annotated = {}      # set of blocks already seen
         self.added_blocks = None # see processblock() below
         self.links_followed = {} # set of links that have ever been followed
@@ -81,7 +57,7 @@
         self.errors = []
 
     def __getstate__(self):
-        attrs = """translator pendingblocks annotated links_followed
+        attrs = """translator genpendingblocks annotated links_followed
         notify bookkeeper frozen policy added_blocks""".split()
         ret = self.__dict__.copy()
         for key, value in ret.items():
@@ -212,19 +188,47 @@
             else:
                 self.mergeinputargs(graph, block, cells)
             if not self.annotated[block]:
-                self.pendingblocks[block] = graph
+                self.schedulependingblock(graph, block)
+
+    def schedulependingblock(self, graph, block):
+        # 'self.genpendingblocks' is a list of dictionaries which is
+        # logically equivalent to just one dictionary.  But we keep a
+        # 'generation' number on each block (=key), and whenever we
+        # process a block, we increase its generation number.  The
+        # block is added to the 'genpendingblocks' indexed by its
+        # generation number.  See complete_pending_blocks() below.
+        generation = getattr(block, 'generation', 0)
+        self.genpendingblocks[generation][block] = graph
 
     def complete_pending_blocks(self):
-        while self.pendingblocks:
-            block, graph = self.pendingblocks.popitem()
-            self.processblock(graph, block)
+        while True:
+            # Find the first of the dictionaries in 'self.genpendingblocks'
+            # which is not empty
+            gen = 0
+            for pendingblocks in self.genpendingblocks:
+                if pendingblocks:
+                    break
+                gen += 1
+            else:
+                return    # all empty => done
+
+            gen += 1   # next generation number
+            if len(self.genpendingblocks) == gen:
+                self.genpendingblocks.append({})
+
+            # Process all blocks at this level
+            # (if any gets re-inserted, it will be into the next level)
+            while pendingblocks:
+                block, graph = pendingblocks.popitem()
+                block.generation = gen
+                self.processblock(graph, block)
 
     def complete(self):
         """Process pending blocks until none is left."""
         while True:
             self.complete_pending_blocks()
             self.policy.no_more_blocks_to_annotate(self)
-            if not self.pendingblocks:
+            if not any(self.genpendingblocks):
                 break   # finished
         # make sure that the return variables of all graphs is annotated
         if self.added_blocks is not None:
@@ -309,21 +313,15 @@
     #___ interface for annotator.bookkeeper _______
 
     def recursivecall(self, graph, whence, inputcells):
-        if isinstance(whence, tuple):
+        if whence is not None:
             parent_graph, parent_block, parent_index = whence
             tag = parent_block, parent_index
             self.translator.update_call_graph(parent_graph, graph, tag)
-        # self.notify[graph.returnblock] is a dictionary of call
-        # points to this func which triggers a reflow whenever the
-        # return block of this graph has been analysed.
-        callpositions = self.notify.setdefault(graph.returnblock, {})
-        if whence is not None:
-            if callable(whence):
-                def callback():
-                    whence(self, graph)
-            else:
-                callback = whence
-            callpositions[callback] = True
+            # self.notify[graph.returnblock] is a set of call
+            # points to this func which triggers a reflow whenever the
+            # return block of this graph has been analysed.
+            returnpositions = self.notify.setdefault(graph.returnblock, set())
+            returnpositions.add(whence)
 
         # generalize the function's input arguments
         self.addpendingblock(graph, graph.startblock, inputcells)
@@ -416,7 +414,7 @@
     def reflowpendingblock(self, graph, block):
         assert not self.frozen
         assert graph not in self.fixed_graphs
-        self.pendingblocks[block] = graph
+        self.schedulependingblock(graph, block)
         assert block in self.annotated
         self.annotated[block] = False  # must re-flow
         self.blocked_blocks[block] = (graph, None)
@@ -574,12 +572,8 @@
                 self.follow_link(graph, link, constraints)
 
         if block in self.notify:
-            # reflow from certain positions when this block is done
-            for callback in self.notify[block]:
-                if isinstance(callback, tuple):
-                    self.reflowfromposition(callback) # callback is a position
-                else:
-                    callback()
+            for position in self.notify[block]:
+                self.reflowfromposition(position)
 
 
     def follow_link(self, graph, link, constraints):
diff --git a/rpython/annotator/bookkeeper.py b/rpython/annotator/bookkeeper.py
--- a/rpython/annotator/bookkeeper.py
+++ b/rpython/annotator/bookkeeper.py
@@ -547,10 +547,8 @@
         (position_key, "first") and (position_key, "second").
 
         In general, "unique_key" should somehow uniquely identify where
-        the call is in the source code, and "callback" can be either a
-        position_key to reflow from when we see more general results,
-        or a real callback function that will be called with arguments
-        # "(annotator, called_graph)" whenever the result is generalized.
+        the call is in the source code, and "callback" is a
+        position_key to reflow from when we see more general results.
 
         "replace" can be set to a list of old unique_key values to
         forget now, because the given "unique_key" replaces them.
diff --git a/rpython/annotator/dictdef.py b/rpython/annotator/dictdef.py
--- a/rpython/annotator/dictdef.py
+++ b/rpython/annotator/dictdef.py
@@ -1,5 +1,5 @@
 from rpython.annotator.model import (
-    s_ImpossibleValue, SomeInteger, s_Bool, union)
+    s_ImpossibleValue, SomeInteger, s_Bool, union, AnnotatorError)
 from rpython.annotator.listdef import ListItem
 from rpython.rlib.objectmodel import compute_hash
 
@@ -51,23 +51,19 @@
 
         s_key = self.s_value
 
-        def check_eqfn(annotator, graph):
-            s = annotator.binding(graph.getreturnvar())
-            assert s_Bool.contains(s), (
+        s = self.bookkeeper.emulate_pbc_call(
+            myeq, self.s_rdict_eqfn, [s_key, s_key], replace=replace_othereq)
+        if not s_Bool.contains(s):
+            raise AnnotatorError(
                 "the custom eq function of an r_dict must return a boolean"
                 " (got %r)" % (s,))
-        self.bookkeeper.emulate_pbc_call(myeq, self.s_rdict_eqfn, [s_key, s_key],
-                                         replace=replace_othereq,
-                                         callback = check_eqfn)
 
-        def check_hashfn(annotator, graph):
-            s = annotator.binding(graph.getreturnvar())
-            assert SomeInteger().contains(s), (
+        s = self.bookkeeper.emulate_pbc_call(
+            myhash, self.s_rdict_hashfn, [s_key], replace=replace_otherhash)
+        if not SomeInteger().contains(s):
+            raise AnnotatorError(
                 "the custom hash function of an r_dict must return an integer"
                 " (got %r)" % (s,))
-        self.bookkeeper.emulate_pbc_call(myhash, self.s_rdict_hashfn, [s_key],
-                                         replace=replace_otherhash,
-                                         callback = check_hashfn)
 
 
 class DictValue(ListItem):
@@ -93,11 +89,11 @@
         self.force_non_null = force_non_null
 
     def read_key(self, position_key):
-        self.dictkey.read_locations[position_key] = True
+        self.dictkey.read_locations.add(position_key)
         return self.dictkey.s_value
 
     def read_value(self, position_key):
-        self.dictvalue.read_locations[position_key] = True
+        self.dictvalue.read_locations.add(position_key)
         return self.dictvalue.s_value
 
     def same_as(self, other):
diff --git a/rpython/annotator/listdef.py b/rpython/annotator/listdef.py
--- a/rpython/annotator/listdef.py
+++ b/rpython/annotator/listdef.py
@@ -30,7 +30,7 @@
         self.s_value = s_value
         self.bookkeeper = bookkeeper
         self.itemof = {}  # set of all ListDefs using this ListItem
-        self.read_locations = {}
+        self.read_locations = set()
         if bookkeeper is None:
             self.dont_change_any_more = True
 
@@ -95,7 +95,7 @@
                 self.notify_update()
             if s_new_value != s_other_value:
                 other.notify_update()
-            self.read_locations.update(other.read_locations)
+            self.read_locations |= other.read_locations
 
     def patch(self):
         for listdef in self.itemof:
@@ -130,7 +130,7 @@
         self.listitem.itemof[self] = True
 
     def read_item(self, position_key):
-        self.listitem.read_locations[position_key] = True
+        self.listitem.read_locations.add(position_key)
         return self.listitem.s_value
 
     def same_as(self, other):
diff --git a/rpython/annotator/test/test_annrpython.py b/rpython/annotator/test/test_annrpython.py
--- a/rpython/annotator/test/test_annrpython.py
+++ b/rpython/annotator/test/test_annrpython.py
@@ -2141,28 +2141,6 @@
         assert (fdesc.get_s_signatures((2, (), False))
                 == [([someint,someint],someint)])
 
-    def test_emulated_pbc_call_callback(self):
-        def f(a,b):
-            return a + b
-        from rpython.annotator import annrpython
-        a = annrpython.RPythonAnnotator()
-        from rpython.annotator import model as annmodel
-
-        memo = []
-        def callb(ann, graph):
-            memo.append(annmodel.SomeInteger() == ann.binding(graph.getreturnvar()))
-
-        s_f = a.bookkeeper.immutablevalue(f)
-        s = a.bookkeeper.emulate_pbc_call('f', s_f, [annmodel.SomeInteger(), annmodel.SomeInteger()],
-                                          callback=callb)
-        assert s == annmodel.SomeImpossibleValue()
-        a.complete()
-
-        assert a.binding(graphof(a, f).getreturnvar()).knowntype == int
-        assert len(memo) >= 1
-        for t in memo:
-            assert t
-
     def test_iterator_union(self):
         def it(d):
             return d.iteritems()
diff --git a/rpython/config/support.py b/rpython/config/support.py
--- a/rpython/config/support.py
+++ b/rpython/config/support.py
@@ -41,8 +41,8 @@
     Function to determine if your system comes with PAX protection.
     """
     if sys.platform.startswith('linux'):
-        # we need a running process PID and 1 is always running
-        with open("/proc/1/status") as fd:
+        # use PID of current process for the check
+        with open("/proc/self/status") as fd:
             data = fd.read()
         if 'PaX' in data:
             return True
diff --git a/rpython/flowspace/model.py b/rpython/flowspace/model.py
--- a/rpython/flowspace/model.py
+++ b/rpython/flowspace/model.py
@@ -170,7 +170,7 @@
 
 class Block(object):
     __slots__ = """inputargs operations exitswitch
-                exits blockcolor""".split()
+                exits blockcolor generation""".split()
 
     def __init__(self, inputargs):
         self.inputargs = list(inputargs)  # mixed list of variable/const XXX
diff --git a/rpython/rlib/rerased.py b/rpython/rlib/rerased.py
--- a/rpython/rlib/rerased.py
+++ b/rpython/rlib/rerased.py
@@ -15,6 +15,8 @@
 """
 
 import sys
+from collections import defaultdict
+
 from rpython.annotator import model as annmodel
 from rpython.rtyper.extregistry import ExtRegistryEntry
 from rpython.rtyper.llannotation import lltype_to_annotation
@@ -48,34 +50,29 @@
     def __deepcopy__(self, memo):
         return self
 
-    def _getdict(self, bk):
-        try:
-            dict = bk._erasing_pairs_tunnel
-        except AttributeError:
-            dict = bk._erasing_pairs_tunnel = {}
-        return dict
+class IdentityDesc(object):
+    def __init__(self, bookkeeper):
+        self.bookkeeper = bookkeeper
+        self.s_input = annmodel.s_ImpossibleValue
+        self.reflowpositions = {}
 
-    def enter_tunnel(self, bookkeeper, s_obj):
-        dict = self._getdict(bookkeeper)
-        s_previousobj, reflowpositions = dict.setdefault(
-            self, (annmodel.s_ImpossibleValue, {}))
-        s_obj = annmodel.unionof(s_previousobj, s_obj)
-        if s_obj != s_previousobj:
-            dict[self] = (s_obj, reflowpositions)
-            for position in reflowpositions:
-                bookkeeper.annotator.reflowfromposition(position)
+    def enter_tunnel(self, s_obj):
+        s_obj = annmodel.unionof(self.s_input, s_obj)
+        if s_obj != self.s_input:
+            self.s_input = s_obj
+            for position in self.reflowpositions:
+                self.bookkeeper.annotator.reflowfromposition(position)
 
-    def leave_tunnel(self, bookkeeper):
-        dict = self._getdict(bookkeeper)
-        s_obj, reflowpositions = dict.setdefault(
-            self, (annmodel.s_ImpossibleValue, {}))
-        reflowpositions[bookkeeper.position_key] = True
-        return s_obj
+    def leave_tunnel(self):
+        self.reflowpositions[self.bookkeeper.position_key] = True
+        return self.s_input
 
-    def get_input_annotation(self, bookkeeper):
-        dict = self._getdict(bookkeeper)
-        s_obj, _ = dict[self]
-        return s_obj
+def _get_desc(bk, identity):
+    try:
+        descs = bk._erasing_pairs_descs
+    except AttributeError:
+        descs = bk._erasing_pairs_descs = defaultdict(lambda: IdentityDesc(bk))
+    return descs[identity]
 
 _identity_for_ints = ErasingPairIdentity("int")
 
@@ -94,21 +91,23 @@
         _about_ = erase
 
         def compute_result_annotation(self, s_obj):
-            identity.enter_tunnel(self.bookkeeper, s_obj)
+            desc = _get_desc(self.bookkeeper, identity)
+            desc.enter_tunnel(s_obj)
             return _some_erased()
 
         def specialize_call(self, hop):
             bk = hop.rtyper.annotator.bookkeeper
-            s_obj = identity.get_input_annotation(bk)
+            desc = _get_desc(bk, identity)
             hop.exception_cannot_occur()
-            return _rtype_erase(hop, s_obj)
+            return _rtype_erase(hop, desc.s_input)
 
     class Entry(ExtRegistryEntry):
         _about_ = unerase
 
         def compute_result_annotation(self, s_obj):
             assert _some_erased().contains(s_obj)
-            return identity.leave_tunnel(self.bookkeeper)
+            desc = _get_desc(self.bookkeeper, identity)
+            return desc.leave_tunnel()
 
         def specialize_call(self, hop):
             hop.exception_cannot_occur()
@@ -130,6 +129,7 @@
     def __init__(self, x, identity):
         self._x = x
         self._identity = identity
+
     def __repr__(self):
         return "Erased(%r, %r)" % (self._x, self._identity)
 
@@ -140,7 +140,7 @@
             assert config.translation.taggedpointers, "need to enable tagged pointers to use erase_int"
             return lltype.cast_int_to_ptr(r_self.lowleveltype, value._x * 2 + 1)
         bk = r_self.rtyper.annotator.bookkeeper
-        s_obj = value._identity.get_input_annotation(bk)
+        s_obj = _get_desc(bk, value._identity).s_input
         r_obj = r_self.rtyper.getrepr(s_obj)
         if r_obj.lowleveltype is lltype.Void:
             return lltype.nullptr(r_self.lowleveltype.TO)
@@ -182,9 +182,9 @@
     _type_ = Erased
 
     def compute_annotation(self):
-        identity = self.instance._identity
+        desc = _get_desc(self.bookkeeper, self.instance._identity)
         s_obj = self.bookkeeper.immutablevalue(self.instance._x)
-        identity.enter_tunnel(self.bookkeeper, s_obj)
+        desc.enter_tunnel(s_obj)
         return _some_erased()
 
 # annotation and rtyping support
diff --git a/rpython/rlib/rposix.py b/rpython/rlib/rposix.py
--- a/rpython/rlib/rposix.py
+++ b/rpython/rlib/rposix.py
@@ -1881,7 +1881,8 @@
 
 c_chroot = external('chroot', [rffi.CCHARP], rffi.INT,
                     save_err=rffi.RFFI_SAVE_ERRNO,
-                    macro=_MACRO_ON_POSIX)
+                    macro=_MACRO_ON_POSIX,
+                    compilation_info=ExternalCompilationInfo(includes=['unistd.h']))
 
 @replace_os_function('chroot')
 def chroot(path):
diff --git a/rpython/rlib/rstacklet.py b/rpython/rlib/rstacklet.py
--- a/rpython/rlib/rstacklet.py
+++ b/rpython/rlib/rstacklet.py
@@ -3,6 +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 import rvmprof
 from rpython.rlib.rvmprof import cintf
 
 DEBUG = False
@@ -40,11 +41,13 @@
     def switch(self, stacklet):
         if DEBUG:
             debug.remove(stacklet)
+        rvmprof.stop_sampling()
         x = cintf.save_rvmprof_stack()
         try:
             h = self._gcrootfinder.switch(stacklet)
         finally:
             cintf.restore_rvmprof_stack(x)
+            rvmprof.start_sampling()
         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
@@ -55,9 +55,9 @@
 
     return None
 
-def stop_sampling(space):
+def stop_sampling():
     fd = _get_vmprof().cintf.vmprof_stop_sampling()
     return rffi.cast(lltype.Signed, fd)
 
-def start_sampling(space):
+def start_sampling():
     _get_vmprof().cintf.vmprof_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
@@ -62,7 +62,6 @@
         SHARED.join('compat.c'),
         SHARED.join('machine.c'),
         SHARED.join('vmp_stack.c'),
-        SHARED.join('vmprof_mt.c'),
         SHARED.join('vmprof_memory.c'),
         SHARED.join('vmprof_common.c'),
         # symbol table already in separate_module_files
@@ -70,6 +69,10 @@
     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)
 
 def configure_libbacktrace_linux():
diff --git a/rpython/rlib/rvmprof/test/test_rvmprof.py b/rpython/rlib/rvmprof/test/test_rvmprof.py
--- a/rpython/rlib/rvmprof/test/test_rvmprof.py
+++ b/rpython/rlib/rvmprof/test/test_rvmprof.py
@@ -164,23 +164,25 @@
 
     @rvmprof.vmprof_execute_code("xcode1", lambda self, code, count: code)
     def main(self, code, count):
+        code = self.MyCode('py:main:3:main')
+        rvmprof.register_code(code, self.MyCode.get_name)
+        code = self.MyCode('py:code:7:native_func')
+        rvmprof.register_code(code, self.MyCode.get_name)
         if count > 0:
             return self.main(code, count-1)
         else:
             return self.native_func(100)
 
     def test(self):
-        # XXX: this test is known to fail since rev a4f077ba651c, but buildbot
-        # never ran it. FIXME.
         from vmprof import read_profile
-        from vmprof.show import PrettyPrinter
+        # from vmprof.show import PrettyPrinter
         assert self.rpy_entry_point(3, 0.5) == 42000
         assert self.tmpfile.check()
-        #
+
         prof = read_profile(self.tmpfilename)
         tree = prof.get_tree()
-        p = PrettyPrinter()
-        p._print_tree(tree)
+        # p = PrettyPrinter()
+        # p._print_tree(tree)
         def walk(tree, symbols):
             symbols.append(tree.name)
             if len(tree.children) == 0:
@@ -189,7 +191,7 @@
                 walk(child, symbols)
         symbols = []
         walk(tree, symbols)
-        not_found = ['n:native_func']
+        not_found = ['py:code:7:native_func']
         for sym in symbols:
             for i,name in enumerate(not_found):
                 if sym.startswith(name):
diff --git a/rpython/rlib/test/test_rarithmetic.py b/rpython/rlib/test/test_rarithmetic.py
--- a/rpython/rlib/test/test_rarithmetic.py
+++ b/rpython/rlib/test/test_rarithmetic.py
@@ -2,7 +2,7 @@
 from rpython.rtyper.test.test_llinterp import interpret
 from rpython.rlib.rarithmetic import *
 from rpython.rlib.rstring import ParseStringError, ParseStringOverflowError
-from hypothesis import given, strategies
+from hypothesis import given, strategies, assume
 import sys
 import py
 
@@ -404,8 +404,11 @@
 def test_int_c_div_mod(x, y):
     assert int_c_div(~x, y) == -(abs(~x) // y)
     assert int_c_div( x,-y) == -(x // y)
-    if (x, y) == (sys.maxint, 1):
-        py.test.skip("would overflow")
+
+ at given(strategies.integers(min_value=0, max_value=sys.maxint),
+       strategies.integers(min_value=1, max_value=sys.maxint))
+def test_int_c_div_mod_2(x, y):
+    assume((x, y) != (sys.maxint, 1))  # This case would overflow
     assert int_c_div(~x,-y) == +(abs(~x) // y)
     for x1 in [x, ~x]:
         for y1 in [y, -y]:
diff --git a/rpython/rlib/test/test_rstacklet.py b/rpython/rlib/test/test_rstacklet.py
--- a/rpython/rlib/test/test_rstacklet.py
+++ b/rpython/rlib/test/test_rstacklet.py
@@ -10,6 +10,8 @@
 from rpython.config.translationoption import DEFL_ROOTFINDER_WITHJIT
 from rpython.rlib import rrandom, rgc
 from rpython.rlib.rarithmetic import intmask
+from rpython.rlib.nonconst import NonConstant
+from rpython.rlib import rvmprof
 from rpython.rtyper.lltypesystem import lltype, llmemory, rffi
 from rpython.translator.c.test.test_standalone import StandaloneTests
 
@@ -273,7 +275,23 @@
         llmemory.raw_free(raw)
 
 
+# <vmprof-hack>
+# bah, we need to make sure that vmprof_execute_code is annotated, else
+# rvmprof.c does not compile correctly
+class FakeVMProfCode(object):
+    pass
+rvmprof.register_code_object_class(FakeVMProfCode, lambda code: 'name')
+ at rvmprof.vmprof_execute_code("xcode1", lambda code, num: code)
+def fake_vmprof_main(code, num):
+    return 42
+# </vmprof-hack>
+
 def entry_point(argv):
+    # <vmprof-hack>
+    if NonConstant(False):
+        fake_vmprof_main(FakeVMProfCode(), 42)
+    # </vmprof-hack>
+    #
     seed = 0
     if len(argv) > 1:
         seed = int(argv[1])


More information about the pypy-commit mailing list