Commits

wlav committed c31d7ee Merge

merge default into branch; re-enable test_datatypes.py on 32b for testing

Comments (0)

Files changed (37)

pypy/doc/release-2.3.0.rst

     http://pypy.org/download.html
 
 We would like to thank our donors for the continued support of the PyPy
-project. We showed quite a bit of progress on all three projects (see below)
-and we're slowly running out of funds.
-Please consider donating more so we can finish those projects!  The three
-projects are:
+project, and for those who donate to our three sub-projects.
+We showed quite a bit of progress 
+but we're slowly running out of funds.
+Please consider donating more, or even better convince your employer to donate,
+so we can finish those projects!  The three sub-projects are:
 
 * `Py3k`_ (supporting Python 3.x): the release PyPy3 2.2 is imminent.
 
 * `STM`_ (software transactional memory): a preview will be released very soon,
   once we fix a few bugs
 
-* `NumPy`_ the work done is included in the PyPy 2.2 release. More details below.
+* `NumPy`_ which is included in the PyPy 2.3 release. More details below.
 
 .. _`Py3k`: http://pypy.org/py3donate.html
 .. _`STM`: http://pypy.org/tmdonate2.html
 =============
 
 PyPy is a very compliant Python interpreter, almost a drop-in replacement for
-CPython 2.7. It's fast (`pypy 2.2 and cpython 2.7.2`_ performance comparison;
-note that the latest cpython is not faster than cpython 2.7.2)
+CPython 2.7. It's fast (`pypy 2.3 and cpython 2.7.x`_ performance comparison;
+note that cpython's speed has not changed since 2.7.2)
 due to its integrated tracing JIT compiler.
 
 This release supports x86 machines running Linux 32/64, Mac OS X 64, Windows,
 bit python is still stalling, we would welcome a volunteer
 to `handle that`_.
 
-.. _`pypy 2.2 and cpython 2.7.2`: http://speed.pypy.org
+.. _`pypy 2.3 and cpython 2.7.x`: http://speed.pypy.org
 .. _`handle that`: http://doc.pypy.org/en/latest/windows.html#what-is-missing-for-a-full-64-bit-translation
 
 Highlights
 ==========
 
-Bugfixes
+Bugfixes 
 --------
 
 Many issues were cleaned up after being reported by users to https://bugs.pypy.org (ignore the bad SSL certificate) or on IRC at #pypy. Note that we consider
 * The ARM port no longer crashes on unaligned memory access to floats and doubles,
   and singlefloats are supported in the JIT.
 
-* Generators are faster since they now skip unecessary cleanup
+* Generators are faster since they now skip unnecessary cleanup
 
 * A first time contributor simplified JIT traces by adding integer bound
   propagation in indexing and logical operations.
 
 * Fix a rpython bug with loop-unrolling that appeared in the `HippyVM`_ PHP port
 
+* Support for corner cases on objects with __int__ and __float__ methods
+
 .. _`HippyVM`: http://www.hippyvm.com
 
 New Platforms and Features
 
 * Support for precompiled headers in the build process for MSVC
 
-* Support for objects with __int__ and __float__ methods
-
 * Tweak support of errno in cpyext (the PyPy implemenation of the capi)
 
 
 * A cffi-based ``numpy.random`` module is available as a branch in the numpy
   repository, it will be merged soon after this release.
 
-* enhancements to the PyPy JIT were made to support virtualizing the raw_store/raw_load memory operations used in numpy arrays. Further work remains here in virtualizing the alloc_raw_storage when possible. This will allow scalars to have storages but still be virtualized when possible in loops.
+* enhancements to the PyPy JIT were made to support virtualizing the raw_store/raw_load 
+  memory operations used in numpy arrays. Further work remains here in virtualizing the 
+  alloc_raw_storage when possible. This will allow scalars to have storages but still be 
+  virtualized when possible in loops.
 
 Cheers
+
 The PyPy Team
 

pypy/doc/whatsnew-2.3.0.rst

 
 .. branch: refactor-buffer-api
 Properly implement old/new buffer API for objects and start work on replacing bufferstr usage
+
+.. branch: issue1430
+Add a lock for unsafe calls to gethostbyname and gethostbyaddr
+

pypy/doc/whatsnew-head.rst

 =======================
 
 .. this is a revision shortly after release-2.3.x
-.. startrev: 0524dae88c75
+.. startrev: 0f75ad4d14ce
 
-

pypy/interpreter/baseobjspace.py

     def allocate_lock(self):
         """Return an interp-level Lock object if threads are enabled,
         and a dummy object if they are not."""
-        if self.config.objspace.usemodules.thread:
-            # we use a sub-function to avoid putting the 'import' statement
-            # here, where the flow space would see it even if thread=False
-            return self.__allocate_lock()
-        else:
-            return dummy_lock
-
-    def __allocate_lock(self):
-        from rpython.rlib.rthread import allocate_lock, error
+        from rpython.rlib import rthread
+        if not self.config.objspace.usemodules.thread:
+            return rthread.dummy_lock
         # hack: we can't have prebuilt locks if we're translating.
         # In this special situation we should just not lock at all
         # (translation is not multithreaded anyway).
         if not we_are_translated() and self.config.translating:
             raise CannotHaveLock()
         try:
-            return allocate_lock()
-        except error:
+            return rthread.allocate_lock()
+        except rthread.error:
             raise OperationError(self.w_RuntimeError,
                                  self.wrap("out of resources"))
 
 
     def _getarg_error(self, expected, w_obj):
         if self.is_none(w_obj):
-            name = "None"
+            e = oefmt(self.w_TypeError, "must be %s, not None", expected)
         else:
-            name = self.type(w_obj).get_module_type_name()
-        raise oefmt(self.w_TypeError, "must be %s, not %s", expected, name)
+            e = oefmt(self.w_TypeError, "must be %s, not %T", expected, w_obj)
+        raise e
 
     @specialize.arg(1)
     def getarg_w(self, code, w_obj):
         return space.getitem(w_glob, space.wrap('anonymous'))
 
 
-class DummyLock(object):
-    def acquire(self, flag):
-        return True
-
-    def release(self):
-        pass
-
-    def _freeze_(self):
-        return True
-
-    def __enter__(self):
-        pass
-
-    def __exit__(self, *args):
-        pass
-
-dummy_lock = DummyLock()
-
 # Table describing the regular part of the interface of object spaces,
 # namely all methods which only take w_ arguments and return a w_ result
 # (if any).

pypy/interpreter/error.py

                     value = getattr(self, attr)
                     if fmt == 'R':
                         result = space.str_w(space.repr(value))
-                    elif fmt in 'NT':
-                        if fmt == 'T':
-                            value = space.type(value)
+                    elif fmt == 'T':
+                        result = space.type(value).get_module_type_name()
+                    elif fmt == 'N':
                         result = value.getname(space)
                     else:
                         result = str(value)
 
     %N - The result of w_arg.getname(space)
     %R - The result of space.str_w(space.repr(w_arg))
-    %T - The result of space.type(w_arg).getname(space)
+    %T - The result of space.type(w_arg).get_module_type_name()
 
     """
     if not len(args):

pypy/interpreter/gateway.py

                            return x+y
                     ''')
     """
+    prefix = ""
     if not isinstance(source, str):
+        flags = source.__code__.co_flags
         source = py.std.inspect.getsource(source).lstrip()
         while source.startswith(('@py.test.mark.', '@pytest.mark.')):
             # these decorators are known to return the same function
             source = source[source.find('\n') + 1:].lstrip()
         assert source.startswith("def "), "can only transform functions"
         source = source[4:]
+        import __future__
+        if flags & __future__.CO_FUTURE_DIVISION:
+            prefix += "from __future__ import division\n"
+        if flags & __future__.CO_FUTURE_ABSOLUTE_IMPORT:
+            prefix += "from __future__ import absolute_import\n"
+        if flags & __future__.CO_FUTURE_PRINT_FUNCTION:
+            prefix += "from __future__ import print_function\n"
+        if flags & __future__.CO_FUTURE_UNICODE_LITERALS:
+            prefix += "from __future__ import unicode_literals\n"
     p = source.find('(')
     assert p >= 0
     funcname = source[:p].strip()
     source = source[p:]
     assert source.strip()
-    funcsource = "def %s%s\n" % (funcname, source)
+    funcsource = prefix + "def %s%s\n" % (funcname, source)
     #for debugging of wrong source code: py.std.parser.suite(funcsource)
     a = applevel(funcsource, filename=filename)
     return a.interphook(funcname)

pypy/interpreter/test/test_gateway.py

-
 # -*- coding: utf-8 -*-
 
+from __future__ import division, print_function  # for test_app2interp_future
 from pypy.interpreter import gateway, argument
 from pypy.interpreter.gateway import ObjSpace, W_Root, WrappedDefault
 from pypy.interpreter.signature import Signature
 import py
 import sys
 
+
 class FakeFunc(object):
     def __init__(self, space, name):
         self.space = space
         self.name = name
         self.defs_w = []
 
+
 class TestBuiltinCode:
     def test_signature(self):
         def c(space, w_x, w_y, hello_w):
         w_result = code.funcrun(FakeFunc(self.space, "c"), args)
         assert self.space.eq_w(w_result, w(1020))
 
+
 class TestGateway:
-
     def test_app2interp(self):
         w = self.space.wrap
         def app_g3(a, b):
         args = gateway.Arguments(self.space, [w(6)], ['hello', 'world'], [w(7), w(8)])
         assert self.space.int_w(gg(self.space, w(3), args)) == 213
 
+    def test_app2interp_future(self):
+        w = self.space.wrap
+        def app_g3(a, b):
+            print(end='')
+            return a / b
+        g3 = gateway.app2interp_temp(app_g3)
+        assert self.space.eq_w(g3(self.space, w(1), w(4),), w(0.25))
+
     def test_interp2app(self):
         space = self.space
         w = space.wrap
         w_app_f = self.space.wrap(app_f)
 
         assert isinstance(w_app_f.code, gateway.BuiltinCode2)
-        
+
         called = []
         fastcall_2 = w_app_f.code.fastcall_2
         def witness_fastcall_2(space, w_func, w_a, w_b):
 
 
 class TestPassThroughArguments:
-
     def test_pass_trough_arguments0(self):
         space = self.space
 
 
 
 class AppTestKeywordsToBuiltinSanity(object):
-
     def test_type(self):
         class X(object):
             def __init__(self, **kw):
 
         d.update(**{clash: 33})
         dict.update(d, **{clash: 33})
-

pypy/module/_ast/test/test_ast.py

         ast = self.ast
         assert isinstance(ast.__version__, str)
 
+    def test_flags(self):
+        skip("broken")
+        from copy_reg import _HEAPTYPE
+        assert self.ast.Module.__flags__ & _HEAPTYPE
+
     def test_build_ast(self):
         ast = self.ast
         mod = self.get_ast("x = 4")
         x = ast.Num()
         assert x._fields == ('n',)
         exc = raises(AttributeError, getattr, x, 'n')
-        assert exc.value.args[0] == "'Num' object has no attribute 'n'"
+        assert "Num' object has no attribute 'n'" in exc.value.args[0]
 
         x = ast.Num(42)
         assert x.n == 42
         exc = raises(AttributeError, getattr, x, 'lineno')
-        assert exc.value.args[0] == "'Num' object has no attribute 'lineno'"
+        assert "Num' object has no attribute 'lineno'" in exc.value.args[0]
 
         y = ast.Num()
         x.lineno = y
         assert x.lineno == y
 
         exc = raises(AttributeError, getattr, x, 'foobar')
-        assert exc.value.args[0] == "'Num' object has no attribute 'foobar'"
+        assert "Num' object has no attribute 'foobar'" in exc.value.args[0]
 
         x = ast.Num(lineno=2)
         assert x.lineno == 2
         raises(TypeError, ast.Num, 1, 2, lineno=0)
 
     def test_issue1680_nonseq(self):
+        # Test deleting an attribute manually
 
-        # Test deleting an attribute manually
-         
         _ast = self.ast
         mod = self.get_ast("self.attr")
         assert isinstance(mod, _ast.Module)
         assert not hasattr(mod.body[0], 'name')
 
     def test_issue1680_seq(self):
+        # Test deleting an attribute manually
 
-        # Test deleting an attribute manually
-         
         _ast = self.ast
         mod = self.get_ast("self.attr")
         assert isinstance(mod, _ast.Module)
         import ast
         num_node = ast.Num(n=2, lineno=2, col_offset=3)
         dict_res = num_node.__dict__
-        
         assert dict_res == {'n':2, 'lineno':2, 'col_offset':3}
-    
+
     def test_issue1673_Num_notfullinit(self):
         import ast
         import copy
         assert num_node.n == 2
         assert num_node.lineno == 2
         num_node2 = copy.deepcopy(num_node)
-    
+
     def test_issue1673_Num_fullinit(self):
         import ast
         import copy 
         assert num_node.col_offset == num_node2.col_offset
         dict_res = num_node2.__dict__
         assert dict_res == {'n':2, 'lineno':2, 'col_offset':3}
-          
+
     def test_issue1673_Str(self):
         import ast
         import copy
         str_node2 = copy.deepcopy(str_node)
         dict_res = str_node2.__dict__
         assert dict_res == {'n':2, 'lineno':2}
-    

pypy/module/_lsprof/interp_lsprof.py

             self.tt, self.it, calls_repr))
 
     def get_code(self, space):
-        return self.frame
+        return returns_code(space, self.frame)
 
 W_StatsEntry.typedef = TypeDef(
     'StatsEntry',
             frame_repr, self.callcount, self.reccallcount, self.tt, self.it))
 
     def get_code(self, space):
-        return self.frame
+        return returns_code(space, self.frame)
 
 W_StatsSubEntry.typedef = TypeDef(
     'SubStatsEntry',
         name = '?'
     if class_name is None:
         class_name = w_type.getname(space)    # if the rest doesn't work
-    return "{method '%s' of '%s' objects}" % (name, class_name)
+    return "<method '%s' of '%s' objects>" % (name, class_name)
 
 
 def create_spec_for_function(space, w_func):
+    assert isinstance(w_func, Function)
     if w_func.w_module is not None:
         module = space.str_w(w_func.w_module)
         if module != '__builtin__':
-            return '{%s.%s}' % (module, w_func.name)
-    return '{%s}' % w_func.name
+            return '<%s.%s>' % (module, w_func.name)
+    return '<%s>' % w_func.name
 
 
-def create_spec_for_object(space, w_obj):
-    class_name = space.type(w_obj).getname(space)
-    return "{'%s' object}" % (class_name,)
+def create_spec_for_object(space, w_type):
+    class_name = w_type.getname(space)
+    return "<'%s' object>" % (class_name,)
 
 
-def create_spec(space, w_arg):
+class W_DelayedBuiltinStr(W_Root):
+    # This class should not be seen at app-level, but is useful to
+    # contain a (w_func, w_type) pair returned by prepare_spec().
+    # Turning this pair into a string cannot be done eagerly in
+    # an @elidable function because of space.str_w(), but it can
+    # be done lazily when we really want it.
+
+    _immutable_fields_ = ['w_func', 'w_type']
+
+    def __init__(self, w_func, w_type):
+        self.w_func = w_func
+        self.w_type = w_type
+        self.w_string = None
+
+    def wrap_string(self, space):
+        if self.w_string is None:
+            if self.w_type is None:
+                s = create_spec_for_function(space, self.w_func)
+            elif self.w_func is None:
+                s = create_spec_for_object(space, self.w_type)
+            else:
+                s = create_spec_for_method(space, self.w_func, self.w_type)
+            self.w_string = space.wrap(s)
+        return self.w_string
+
+W_DelayedBuiltinStr.typedef = TypeDef(
+    'DelayedBuiltinStr',
+    __str__ = interp2app(W_DelayedBuiltinStr.wrap_string),
+)
+
+def returns_code(space, w_frame):
+    if isinstance(w_frame, W_DelayedBuiltinStr):
+        return w_frame.wrap_string(space)
+    return w_frame    # actually a PyCode object
+
+
+def prepare_spec(space, w_arg):
     if isinstance(w_arg, Method):
-        return create_spec_for_method(space, w_arg.w_function, w_arg.w_class)
+        return (w_arg.w_function, w_arg.w_class)
     elif isinstance(w_arg, Function):
-        return create_spec_for_function(space, w_arg)
+        return (w_arg, None)
     else:
-        return create_spec_for_object(space, w_arg)
+        return (None, space.type(w_arg))
+prepare_spec._always_inline_ = True
 
 
 def lsprof_call(space, w_self, frame, event, w_arg):
         w_self._enter_return(code)
     elif event == 'c_call':
         if w_self.builtins:
-            key = create_spec(space, w_arg)
-            w_self._enter_builtin_call(key)
+            w_self._enter_builtin_call(w_arg)
     elif event == 'c_return' or event == 'c_exception':
         if w_self.builtins:
-            key = create_spec(space, w_arg)
-            w_self._enter_builtin_return(key)
+            w_self._enter_builtin_return(w_arg)
     else:
         # ignore or raise an exception???
         pass
                 return entry
             raise
 
-    @jit.elidable
-    def _get_or_make_builtin_entry(self, key, make=True):
+    @jit.elidable_promote()
+    def _get_or_make_builtin_entry(self, w_func, w_type, make):
+        key = (w_func, w_type)
         try:
             return self.builtin_data[key]
         except KeyError:
             if make:
-                entry = ProfilerEntry(self.space.wrap(key))
+                entry = ProfilerEntry(W_DelayedBuiltinStr(w_func, w_type))
                 self.builtin_data[key] = entry
                 return entry
             raise
             context._stop(self, entry)
         self.current_context = context.previous
 
-    def _enter_builtin_call(self, key):
-        self = jit.promote(self)
-        key = jit.promote_string(key)
-        entry = self._get_or_make_builtin_entry(key)
+    def _enter_builtin_call(self, w_arg):
+        w_func, w_type = prepare_spec(self.space, w_arg)
+        entry = self._get_or_make_builtin_entry(w_func, w_type, True)
         self.current_context = ProfilerContext(self, entry)
 
-    def _enter_builtin_return(self, key):
+    def _enter_builtin_return(self, w_arg):
         context = self.current_context
         if context is None:
             return
-        self = jit.promote(self)
-        key = jit.promote_string(key)
+        w_func, w_type = prepare_spec(self.space, w_arg)
         try:
-            entry = self._get_or_make_builtin_entry(key, False)
+            entry = self._get_or_make_builtin_entry(w_func, w_type, False)
         except KeyError:
             pass
         else:

pypy/module/_lsprof/test/test_cprofile.py

         import _lsprof
         assert repr(_lsprof.Profiler) == "<type '_lsprof.Profiler'>"
 
+    def test_builtins(self):
+        import _lsprof
+        prof = _lsprof.Profiler()
+        lst = []
+        prof.enable()
+        lst.append(len(lst))
+        prof.disable()
+        stats = prof.getstats()
+        expected = (
+            "<len>",
+            "<method 'append' of 'list' objects>",
+            "<method 'disable' of '_lsprof.Profiler' objects>",
+        )
+        for entry in stats:
+            assert entry.code in expected
+
+    def test_builtins_callers(self):
+        import _lsprof
+        prof = _lsprof.Profiler(subcalls=True)
+        lst = []
+        def f1():
+            lst.append(len(lst))
+        prof.enable(subcalls=True)
+        f1()
+        prof.disable()
+        stats = prof.getstats()
+        expected = (
+            "<len>",
+            "<method 'append' of 'list' objects>",
+        )
+        by_id = set()
+        for entry in stats:
+            if entry.code == f1.__code__:
+                assert len(entry.calls) == 2
+                for subentry in entry.calls:
+                    assert subentry.code in expected
+                    by_id.add(id(subentry.code))
+            elif entry.code in expected:
+                by_id.add(id(entry.code))
+        #  :-(  cProfile.py relies on the id() of the strings...
+        assert len(by_id) == len(expected)
+
     def test_direct(self):
         import _lsprof
         def getticks():
         stats = prof.getstats()
         entries = {}
         for entry in stats:
-            if not hasattr(entry.code, 'co_name'):
-                print entry.code
-            else:
-                entries[entry.code.co_name] = entry
+            assert hasattr(entry.code, 'co_name')
+            entries[entry.code.co_name] = entry
         efoo = entries['foo']
         assert efoo.callcount == 2
         assert efoo.reccallcount == 1
         entries = {}
         for entry in stats:
             entries[entry.code] = entry
-        efoo = entries[foo.func_code]
-        ebar = entries[bar.func_code]
+        efoo = entries[foo.__code__]
+        ebar = entries[bar.__code__]
         assert 0.9 < efoo.totaltime < 2.9
         # --- cannot test .inlinetime, because it does not include
         # --- the time spent doing the call to time.time()
                             lines.remove(line)
                             break
                     else:
-                        print 'NOT FOUND:', pattern.rstrip('\n')
-                        print '--- GOT ---'
-                        print got
-                        print
-                        print '--- EXPECTED ---'
-                        print expected
+                        print('NOT FOUND: %s' % pattern.rstrip('\n'))
+                        print('--- GOT ---')
+                        print(got)
+                        print('')
+                        print('--- EXPECTED ---')
+                        print(expected)
                         assert False
                 assert not lines
         finally:

pypy/module/_rawffi/test/test__rawffi.py

         s = S(autofree=True)
         b = buffer(s)
         assert len(b) == 40
-        b[4] = 'X'
-        b[:3] = 'ABC'
-        assert b[:6] == 'ABC\x00X\x00'
+        b[4] = b'X'
+        b[:3] = b'ABC'
+        assert b[:6] == b'ABC\x00X\x00'
 
         A = _rawffi.Array('c')
         a = A(10, autofree=True)
-        a[3] = 'x'
+        a[3] = b'x'
         b = buffer(a)
         assert len(b) == 10
-        assert b[3] == 'x'
-        b[6] = 'y'
-        assert a[6] == 'y'
-        b[3:5] = 'zt'
-        assert a[3] == 'z'
-        assert a[4] == 't'
+        assert b[3] == b'x'
+        b[6] = b'y'
+        assert a[6] == b'y'
+        b[3:5] = b'zt'
+        assert a[3] == b'z'
+        assert a[4] == b't'
 
         b = memoryview(a)
         assert len(b) == 10
-        assert b[3] == 'z'
-        b[3] = 'x'
-        assert b[3] == 'x'
+        assert b[3] == b'z'
+        b[3] = b'x'
+        assert b[3] == b'x'
 
     def test_union(self):
         import _rawffi

pypy/module/_socket/__init__.py

     def startup(self, space):
         from rpython.rlib.rsocket import rsocket_startup
         rsocket_startup()
+        from pypy.module._socket.interp_func import State
+        space.fromcache(State).startup(space)
 
     def buildloaders(cls):
         from rpython.rlib import rsocket

pypy/module/_socket/interp_func.py

     Return the true host name, a list of aliases, and a list of IP addresses,
     for a host.  The host argument is a string giving a host name or IP number.
     """
+    lock = space.fromcache(State).netdb_lock
     try:
-        res = rsocket.gethostbyname_ex(host)
+        res = rsocket.gethostbyname_ex(host, lock)
     except SocketError, e:
         raise converted_error(space, e)
     return common_wrapgethost(space, res)
     Return the true host name, a list of aliases, and a list of IP addresses,
     for a host.  The host argument is a string giving a host name or IP number.
     """
+    lock = space.fromcache(State).netdb_lock
     try:
-        res = rsocket.gethostbyaddr(host)
+        res = rsocket.gethostbyaddr(host, lock)
     except SocketError, e:
         raise converted_error(space, e)
     return common_wrapgethost(space, res)
             raise OperationError(space.w_ValueError,
                                  space.wrap('Timeout value out of range'))
     rsocket.setdefaulttimeout(timeout)
+
+class State(object):
+    def __init__(self, space):
+        self.netdb_lock = None
+
+    def startup(self, space):
+        self.netdb_lock = space.allocate_lock()

pypy/module/cppyy/pythonify.py

 # NOT_RPYTHON
 # do not load cppyy here, see _init_pythonify()
-import types, sys
+import types
+import sys
 
 
 # For now, keep namespaces and classes separate as namespaces are extensible
     def __getattr__(self, name):
         try:
             return get_pycppitem(self, name)  # will cache on self
-        except Exception, e:
+        except Exception as e:
             raise AttributeError("%s object has no attribute '%s' (details: %s)" %
                                  (self, name, str(e)))
 
     return self._getitem__unchecked(idx)
 
 def python_style_sliceable_getitem(self, slice_or_idx):
-    if type(slice_or_idx) == types.SliceType:
+    if type(slice_or_idx) == slice:
         nseq = self.__class__()
         nseq += [python_style_getitem(self, i) \
                     for i in range(*slice_or_idx.indices(len(self)))]

pypy/module/cppyy/test/test_datatypes.py

     def test02_instance_data_read_access(self):
         """Test read access to instance public data and verify values"""
 
-        import cppyy, sys
+        import cppyy
         cppyy_test_data = cppyy.gbl.cppyy_test_data
 
         c = cppyy_test_data()
     def test03_instance_data_write_access(self):
         """Test write access to instance public data and verify values"""
 
-        import cppyy, sys
+        import cppyy
         cppyy_test_data = cppyy.gbl.cppyy_test_data
 
         c = cppyy_test_data()
 
         import cppyy
         four_vector = cppyy.gbl.four_vector
-        
+
         t1 = four_vector(1., 2., 3., -4.)
         t2 = four_vector(0., 0., 0.,  0.)
         t3 = four_vector(t1)
-  
+
         assert t1 == t3
         assert t1 != t2
-        
+
         for i in range(4):
             assert t1[i] == t3[i]
 
 
     def test18_object_and_pointer_comparisons(self):
         """Verify object and pointer comparisons"""
-    
-        import cppyy 
+
+        import cppyy
         gbl = cppyy.gbl
 
         c1 = cppyy.bind_object(0, gbl.cppyy_test_data)
 
     def test19_object_validity(self):
         """Test object validity checking"""
-        
+
         from cppyy import gbl
 
         d = gbl.cppyy_test_pod()
-                     
+
         assert d
         assert not not d
 

pypy/module/micronumpy/__init__.py

 
         'set_string_function': 'appbridge.set_string_function',
         'typeinfo': 'descriptor.get_dtype_cache(space).w_typeinfo',
-        'nditer': 'nditer.nditer',
+        'nditer': 'nditer.W_NDIter',
     }
     for c in ['MAXDIMS', 'CLIP', 'WRAP', 'RAISE']:
         interpleveldefs[c] = 'space.wrap(constants.%s)' % c

pypy/module/micronumpy/descriptor.py

         return dtype
 
     def get_name(self):
-        return self.w_box_type.name
+        name = self.w_box_type.name
+        if name.endswith('_'):
+            name = name[:-1]
+        return name
 
     def descr_get_name(self, space):
         name = self.get_name()
-        if name[-1] == '_':
-            name = name[:-1]
         if self.is_flexible() and self.elsize != 0:
             return space.wrap(name + str(self.elsize * 8))
         return space.wrap(name)
             w_box_type=space.gettypefor(boxes.W_ULongBox),
         )
         aliases = {
-            NPY.BOOL:        ['bool', 'bool8'],
+            NPY.BOOL:        ['bool_', 'bool8'],
             NPY.BYTE:        ['byte'],
             NPY.UBYTE:       ['ubyte'],
             NPY.SHORT:       ['short'],
             NPY.CFLOAT:      ['csingle'],
             NPY.CDOUBLE:     ['complex', 'cfloat', 'cdouble'],
             NPY.CLONGDOUBLE: ['clongdouble', 'clongfloat'],
-            NPY.STRING:      ['string', 'str'],
-            NPY.UNICODE:     ['unicode'],
+            NPY.STRING:      ['string_', 'str'],
+            NPY.UNICODE:     ['unicode_'],
         }
         self.alternate_constructors = {
             NPY.BOOL:     [space.w_bool],

pypy/module/micronumpy/nditer.py

              w_op_dtypes=WrappedDefault(None), order=str,
              w_casting=WrappedDefault(None), w_op_axes=WrappedDefault(None),
              w_itershape=WrappedDefault(None), w_buffersize=WrappedDefault(None))
-def nditer(space, w_seq, w_flags, w_op_flags, w_op_dtypes, w_casting, w_op_axes,
-           w_itershape, w_buffersize, order='K'):
+def descr__new__(space, w_subtype, w_seq, w_flags, w_op_flags, w_op_dtypes,
+                 w_casting, w_op_axes, w_itershape, w_buffersize, order='K'):
     return W_NDIter(space, w_seq, w_flags, w_op_flags, w_op_dtypes, w_casting, w_op_axes,
                     w_itershape, w_buffersize, order)
 
-W_NDIter.typedef = TypeDef(
-    'nditer',
+W_NDIter.typedef = TypeDef('nditer',
+    __module__ = 'numpy',
+    __new__ = interp2app(descr__new__),
+
     __iter__ = interp2app(W_NDIter.descr_iter),
     __getitem__ = interp2app(W_NDIter.descr_getitem),
     __setitem__ = interp2app(W_NDIter.descr_setitem),
     shape = GetSetProperty(W_NDIter.descr_get_shape),
     value = GetSetProperty(W_NDIter.descr_get_value),
 )
+W_NDIter.typedef.acceptable_as_base_class = False

pypy/module/micronumpy/test/test_dtypes.py

         assert d.kind == 'b'
         assert dtype(d) is d
         assert dtype('bool') is d
+        assert dtype('bool_') is d
         assert dtype('|b1') is d
         b = '>' if sys.byteorder == 'little' else '<'
         assert dtype(b + 'i4') is not dtype(b + 'i4')
         assert dtype(int).names is None
         assert dtype(int).hasobject is False
         assert dtype(int).subdtype is None
+        assert dtype(str) is dtype('string') is dtype('string_')
+        assert dtype(unicode) is dtype('unicode') is dtype('unicode_')
 
         assert dtype(None) is dtype(float)
 
-        for d in [dtype('<c8'), dtype('>i4')]:
+        for d in [dtype('<c8'), dtype('>i4'), dtype('bool')]:
             for key in ["d[2]", "d['z']", "d[None]"]:
                 exc = raises(KeyError, key)
                 assert exc.value[0] == "There are no fields in dtype %s." % str(d)

pypy/module/micronumpy/test/test_nditer.py

 
 
 class AppTestNDIter(BaseNumpyAppTest):
+    def test_type(self):
+        import numpy as np
+        assert type(np.nditer) is type
+        assert np.nditer.__name__ == 'nditer'
+        assert np.nditer.__module__ == 'numpy'
+        try:
+            class Sub(np.nditer):
+                pass
+        except TypeError as e:
+            assert "not an acceptable base" in str(e)
+        else:
+            assert False
+
     def test_basic(self):
         from numpy import arange, nditer, ndarray
         a = arange(6).reshape(2,3)

pypy/module/pypyjit/test_pypy_c/test_cprofile.py

+import py, sys
+from pypy.module.pypyjit.test_pypy_c.test_00_model import BaseTestPyPyC
+
+class TestCProfile(BaseTestPyPyC):
+
+    def test_cprofile_builtin(self):
+        def main(n):
+            import _lsprof
+            prof = _lsprof.Profiler()
+            i = 0
+            lst = []
+            prof.enable()
+            while i < n:
+                lst.append(i)   # ID: append
+                lst.pop()       # ID: pop
+                i += 1
+            prof.disable()
+            return [(entry.code, entry.callcount) for entry in prof.getstats()]
+        #
+        log = self.run(main, [500])
+        assert sorted(log.result) == [
+            ("<method 'append' of 'list' objects>", 500),
+            ("<method 'disable' of '_lsprof.Profiler' objects>", 1),
+            ("<method 'pop' of 'list' objects>", 500),
+            ]
+        for method in ['append', 'pop']:
+            loop, = log.loops_by_id(method)
+            print loop.ops_by_id(method)
+            # on 32-bit, there is f1=read_timestamp(); ...;
+            # f2=read_timestamp(); f3=call(llong_sub,f1,f2)
+            # which should turn into a single PADDQ/PSUBQ
+            if sys.maxint != 2147483647:
+                assert ' call(' not in repr(loop.ops_by_id(method))
+            assert ' call_may_force(' not in repr(loop.ops_by_id(method))
+            assert ' cond_call(' in repr(loop.ops_by_id(method))

pypy/objspace/fake/checkmodule.py

         mod = __import__('pypy.module.%s' % modname, None, None, ['__doc__'])
         # force computation and record what we wrap
         module = mod.Module(space, W_Root())
+        module.startup(space)
         for name in module.loaders:
             seeobj_w.append(module._load_lazily(space, name))
         if hasattr(module, 'submodules'):

pypy/objspace/std/test/test_strbufobject.py

         assert len(t) == 4
 
     def test_buffer(self):
-        s = 'a'.__add__('b')
-        assert buffer(s) == buffer('ab')
-        assert memoryview(s) == 'ab'
+        s = b'a'.__add__(b'b')
+        assert buffer(s) == buffer(b'ab')
+        assert memoryview(s) == b'ab'
 
     def test_add_strbuf(self):
         # make three strbuf objects

pypy/objspace/std/test/test_typeobject.py

 
 
 class AppTestTypeObject:
-
     def test_abstract_methods(self):
         class X(object):
             pass
         raises(AttributeError, getattr, type, "__abstractmethods__")
         raises(TypeError, "int.__abstractmethods__ = ('abc', )")
 
+    def test_attribute_error(self):
+        class X(object):
+            __module__ = 'test'
+        x = X()
+        exc = raises(AttributeError, "x.a")
+        assert str(exc.value) == "'X' object has no attribute 'a'"
+
     def test_call_type(self):
         assert type(42) is int
         C = type('C', (object,), {'x': lambda: 42})
         assert f.__call__() == ((), {})
         assert f.__call__("hello", "world") == (("hello", "world"), {})
         assert f.__call__(5, bla=6) == ((5,), {"bla": 6})
-        assert f.__call__(a=1, b=2, c=3) == ((), {"a": 1, "b": 2,
-                                                           "c": 3})
+        assert f.__call__(a=1, b=2, c=3) == ((), {"a": 1, "b": 2, "c": 3})
 
     def test_multipleinheritance_fail(self):
         try:
         assert ImmutableDoc.__doc__ == 'foo'
 
     def test_metaclass_conflict(self):
-
         class T1(type):
             pass
         class T2(type):
 
     def test_metaclass_choice(self):
         events = []
-        
+
         class T1(type):
             def __new__(*args):
                 events.append(args)
         assert type(D1) is T1
         assert type(C) is T1
         assert type(G) is T1
-    
+
     def test_descr_typecheck(self):
         raises(TypeError,type.__dict__['__name__'].__get__,1)
         raises(TypeError,type.__dict__['__mro__'].__get__,1)
         z2 = Z2()
         z2.__class__ = Z1
         assert z2.__class__ == Z1
-        
+
         class I(int):
             pass
         class F(float):
             pass
 
         i = I()
-        
         i2 = I()
         i.__class__ = I2
         i2.__class__ = I
         assert i.__class__ ==  I2
         assert i2.__class__ == I
-        
+
         i3 = I3()
         raises(TypeError, "i3.__class__ = I2")
         i3.__class__ = I4
         Abc.__name__ = 'Def'
         assert Abc.__name__ == 'Def'
         raises(TypeError, "Abc.__name__ = 42")
+        try:
+            Abc.__name__ = 'G\x00hi'
+        except ValueError as e:
+            assert str(e) == "__name__ must not contain null bytes"
+        else:
+            assert False
 
     def test_compare(self):
         class A(object):

pypy/objspace/std/typeobject.py

 
     def get_module_type_name(w_self):
         space = w_self.space
-        w_mod = w_self.get_module()
-        if space.isinstance_w(w_mod, space.w_str):
-            mod = space.str_w(w_mod)
-            if mod != '__builtin__':
-                return '%s.%s' % (mod, w_self.name)
+        if not w_self.is_heaptype():
+            w_mod = w_self.get_module()
+            if space.isinstance_w(w_mod, space.w_str):
+                mod = space.str_w(w_mod)
+                if mod != '__builtin__':
+                    return '%s.%s' % (mod, w_self.name)
         return w_self.name
 
     def getname(w_self, space):
     w_type = _check(space, w_type)
     if not w_type.is_heaptype():
         raise oefmt(space.w_TypeError, "can't set %N.__name__", w_type)
-    w_type.name = space.str_w(w_value)
+    name = space.str_w(w_value)
+    if '\x00' in name:
+        raise oefmt(space.w_ValueError, "__name__ must not contain null bytes")
+    w_type.name = name
 
 def descr_get__mro__(space, w_type):
     w_type = _check(space, w_type)

rpython/jit/codewriter/call.py

         # check that the result is really as expected
         if loopinvariant:
             if extraeffect != EffectInfo.EF_LOOPINVARIANT:
-                from rpython.jit.codewriter.policy import log; log.WARNING(
+                raise Exception(
                 "in operation %r: this calls a _jit_loop_invariant_ function,"
                 " but this contradicts other sources (e.g. it can have random"
                 " effects): EF=%s" % (op, extraeffect))
         if elidable:
             if extraeffect not in (EffectInfo.EF_ELIDABLE_CANNOT_RAISE,
                                    EffectInfo.EF_ELIDABLE_CAN_RAISE):
-                from rpython.jit.codewriter.policy import log; log.WARNING(
+                raise Exception(
                 "in operation %r: this calls an _elidable_function_,"
                 " but this contradicts other sources (e.g. it can have random"
                 " effects): EF=%s" % (op, extraeffect))

rpython/jit/metainterp/optimizeopt/optimizer.py

     def forget_numberings(self, box):
         self.optimizer.forget_numberings(box)
 
+    def _can_optimize_call_pure(self, op):
+        arg_consts = []
+        for i in range(op.numargs()):
+            arg = op.getarg(i)
+            const = self.optimizer.get_constant_box(arg)
+            if const is None:
+                return None
+            arg_consts.append(const)
+        else:
+            # all constant arguments: check if we already know the result
+            try:
+                return self.optimizer.call_pure_results[arg_consts]
+            except KeyError:
+                return None
+
 
 class Optimizer(Optimization):
 

rpython/jit/metainterp/optimizeopt/pure.py

             self.emit_operation(nextop)
 
     def optimize_CALL_PURE(self, op):
+        # Step 1: check if all arguments are constant
+        result = self._can_optimize_call_pure(op)
+        if result is not None:
+            # this removes a CALL_PURE with all constant arguments.
+            self.make_constant(op.result, result)
+            self.last_emitted_operation = REMOVED
+            return
+
+        # Step 2: check if all arguments are the same as a previous
+        # CALL_PURE.
         args = self.optimizer.make_args_key(op)
         oldop = self.pure_operations.get(args, None)
         if oldop is not None and oldop.getdescr() is op.getdescr():

rpython/jit/metainterp/optimizeopt/rewrite.py

         return False
 
     def optimize_CALL_PURE(self, op):
-        arg_consts = []
-        for i in range(op.numargs()):
-            arg = op.getarg(i)
-            const = self.get_constant_box(arg)
-            if const is None:
-                break
-            arg_consts.append(const)
-        else:
-            # all constant arguments: check if we already know the result
-            try:
-                result = self.optimizer.call_pure_results[arg_consts]
-            except KeyError:
-                pass
-            else:
-                # this removes a CALL_PURE with all constant arguments.
-                self.make_constant(op.result, result)
-                self.last_emitted_operation = REMOVED
-                return
+        # this removes a CALL_PURE with all constant arguments.
+        # Note that it's also done in pure.py.  For now we need both...
+        result = self._can_optimize_call_pure(op)
+        if result is not None:
+            self.make_constant(op.result, result)
+            self.last_emitted_operation = REMOVED
+            return
         self.emit_operation(op)
 
     def optimize_GUARD_NO_EXCEPTION(self, op):

rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py

         self.optimize_strunicode_loop(ops, expected)
 
     def test_call_pure_vstring_const(self):
-        py.test.skip("implement me")
         ops = """
         []
         p0 = newstr(3)

rpython/rlib/_rsocket_rffi.py

                 'stdio.h',
                 'netdb.h',
                 'arpa/inet.h',
-                'stdint.h', 
+                'stdint.h',
                 'errno.h',
                 )
     if _HAS_AF_PACKET:
 EAI_SOCKTYPE EAI_SYSTEM
 
 IPPROTO_AH IPPROTO_BIP IPPROTO_DSTOPTS IPPROTO_EGP IPPROTO_EON IPPROTO_ESP
-IPPROTO_FRAGMENT IPPROTO_GGP IPPROTO_GRE IPPROTO_HELLO IPPROTO_HOPOPTS 
+IPPROTO_FRAGMENT IPPROTO_GGP IPPROTO_GRE IPPROTO_HELLO IPPROTO_HOPOPTS
 IPPROTO_ICMPV6 IPPROTO_IDP IPPROTO_IGMP IPPROTO_IPCOMP IPPROTO_IPIP
 IPPROTO_IPV4 IPPROTO_IPV6 IPPROTO_MAX IPPROTO_MOBILE IPPROTO_ND IPPROTO_NONE
 IPPROTO_PIM IPPROTO_PUP IPPROTO_ROUTING IPPROTO_RSVP IPPROTO_TCP IPPROTO_TP
 
 SOCK_DGRAM SOCK_RAW SOCK_RDM SOCK_SEQPACKET SOCK_STREAM
 
-SOL_SOCKET SOL_IPX SOL_AX25 SOL_ATALK SOL_NETROM SOL_ROSE 
+SOL_SOCKET SOL_IPX SOL_AX25 SOL_ATALK SOL_NETROM SOL_ROSE
 
 SO_ACCEPTCONN SO_BROADCAST SO_DEBUG SO_DONTROUTE SO_ERROR SO_EXCLUSIVEADDRUSE
 SO_KEEPALIVE SO_LINGER SO_OOBINLINE SO_RCVBUF SO_RCVLOWAT SO_RCVTIMEO
                                               ('nl_pid', rffi.INT),
                                               ('nl_groups', rffi.INT)],
                                              ifdef='AF_NETLINK')
-                                             
+
 CConfig.addrinfo = platform.Struct('struct addrinfo',
                                      [('ai_flags', rffi.INT),
                                       ('ai_family', rffi.INT),

rpython/rlib/rsocket.py

 from rpython.rlib.objectmodel import instantiate, keepalive_until_here
 from rpython.rlib import _rsocket_rffi as _c
 from rpython.rlib.rarithmetic import intmask, r_uint
+from rpython.rlib.rthread import dummy_lock
 from rpython.rtyper.lltypesystem import lltype, rffi
 from rpython.rtyper.lltypesystem.rffi import sizeof, offsetof
 INVALID_SOCKET = _c.INVALID_SOCKET
         paddr = h_addr_list[i]
     return (rffi.charp2str(hostent.c_h_name), aliases, address_list)
 
-def gethostbyname_ex(name):
-    # XXX use gethostbyname_r() if available, and/or use locks if not
+def gethostbyname_ex(name, lock=dummy_lock):
+    # XXX use gethostbyname_r() if available instead of locks
     addr = gethostbyname(name)
-    hostent = _c.gethostbyname(name)
-    return gethost_common(name, hostent, addr)
+    with lock:
+        hostent = _c.gethostbyname(name)
+        return gethost_common(name, hostent, addr)
 
-def gethostbyaddr(ip):
-    # XXX use gethostbyaddr_r() if available, and/or use locks if not
+def gethostbyaddr(ip, lock=dummy_lock):
+    # XXX use gethostbyaddr_r() if available, instead of locks
     addr = makeipaddr(ip)
     assert isinstance(addr, IPAddress)
-    p, size = addr.lock_in_addr()
-    try:
-        hostent = _c.gethostbyaddr(p, size, addr.family)
-    finally:
-        addr.unlock()
-    return gethost_common(ip, hostent, addr)
+    with lock:
+        p, size = addr.lock_in_addr()
+        try:
+            hostent = _c.gethostbyaddr(p, size, addr.family)
+        finally:
+            addr.unlock()
+        return gethost_common(ip, hostent, addr)
 
 def getaddrinfo(host, port_or_service,
                 family=AF_UNSPEC, socktype=0, proto=0, flags=0,

rpython/rlib/rthread.py

-
 from rpython.rtyper.lltypesystem import rffi, lltype, llmemory
 from rpython.translator.tool.cbuild import ExternalCompilationInfo
 from rpython.conftest import cdir
     assert len(y) == 0
     return rffi.cast(lltype.Signed, ll_start_new_thread(x))
 
+class DummyLock(object):
+    def acquire(self, flag):
+        return True
+
+    def release(self):
+        pass
+
+    def _freeze_(self):
+        return True
+
+    def __enter__(self):
+        pass
+
+    def __exit__(self, *args):
+        pass
+
+dummy_lock = DummyLock()
+
 class Lock(object):
     """ Container for low-level implementation
     of a lock object

rpython/rlib/test/test_rsocket.py

 from rpython.rlib.rsocket import *
 import socket as cpy_socket
 
+
 def setup_module(mod):
     rsocket_startup()
 
             py.test.fail("could not find the localhost address in %r"
                          % (address_list,))
 
+def test_thread_safe_gethostbyname_ex():
+    import threading
+    nthreads = 10
+    domain = 'google.com'
+    result = [0] * nthreads
+    threads = [None] * nthreads
+    lock = threading.Lock()
+    def lookup_name(i):
+        name, aliases, address_list = gethostbyname_ex(domain, lock)
+        if name == domain:
+            result[i] += 1
+    for i in range(nthreads):
+        threads[i] = threading.Thread(target = lookup_name, args=[i])
+        threads[i].start()
+    for i in range(nthreads):
+        threads[i].join()
+    assert sum(result) == nthreads
+
+def test_thread_safe_gethostbyaddr():
+    import threading
+    nthreads = 10
+    ip = '8.8.8.8'
+    domain = gethostbyaddr(ip)[0]
+    result = [0] * nthreads
+    threads = [None] * nthreads
+    lock = threading.Lock()
+    def lookup_addr(ip, i):
+        name, aliases, address_list = gethostbyaddr(ip, lock)
+        if name == domain:
+            result[i] += 1
+    for i in range(nthreads):
+        threads[i] = threading.Thread(target = lookup_addr, args=[ip, i])
+        threads[i].start()
+    for i in range(nthreads):
+        threads[i].join()
+    assert sum(result) == nthreads
+
 def test_gethostbyaddr():
     try:
         cpy_socket.gethostbyaddr("::1")

rpython/translator/c/gcc/trackgcroot.py

             return self.visit_ret(line)
         return []
 
+    def visit_ud2(self, line):
+        return InsnStop("ud2")    # unreachable instruction
+
     def visit_jmp(self, line):
         tablelabels = []
         match = self.r_jmp_switch.match(line)

rpython/translator/c/genc.py

 
         #XXX: this conditional part is not tested at all
         if self.config.translation.gcrootfinder == 'asmgcc':
-            trackgcfiles = [cfile[:cfile.rfind('.')] for cfile in mk.cfiles]
             if self.translator.platform.name == 'msvc':
-                trackgcfiles = [f for f in trackgcfiles
-                                if f.startswith(('implement', 'testing',
-                                                 '../module_cache/module'))]
-            sfiles = ['%s.s' % (c,) for c in trackgcfiles]
-            lblsfiles = ['%s.lbl.s' % (c,) for c in trackgcfiles]
-            gcmapfiles = ['%s.gcmap' % (c,) for c in trackgcfiles]
-            mk.definition('ASMFILES', sfiles)
-            mk.definition('ASMLBLFILES', lblsfiles)
-            mk.definition('GCMAPFILES', gcmapfiles)
-            if self.translator.platform.name == 'msvc':
-                mk.definition('DEBUGFLAGS', '-MD -Zi')
+                raise Exception("msvc no longer supports asmgcc")
+            if self.config.translation.shared:
+                mk.definition('DEBUGFLAGS', '-O2 -fomit-frame-pointer -g -fPIC')
             else:
-                if self.config.translation.shared:
-                    mk.definition('DEBUGFLAGS', '-O2 -fomit-frame-pointer -g -fPIC')
-                else:
-                    mk.definition('DEBUGFLAGS', '-O2 -fomit-frame-pointer -g')
+                mk.definition('DEBUGFLAGS', '-O2 -fomit-frame-pointer -g')
 
             if self.config.translation.shared:
                 mk.definition('PYPY_MAIN_FUNCTION', "pypy_main_startup")
 
             mk.definition('PYTHON', get_recent_cpython_executable())
 
-            if self.translator.platform.name == 'msvc':
-                lblofiles = []
-                for cfile in mk.cfiles:
-                    f = cfile[:cfile.rfind('.')]
-                    if f in trackgcfiles:
-                        ofile = '%s.lbl.obj' % (f,)
-                    else:
-                        ofile = '%s.obj' % (f,)
+            mk.definition('GCMAPFILES', '$(subst .c,.gcmap,$(SOURCES))')
+            mk.definition('OBJECTS1', '$(subst .c,.o,$(SOURCES))')
+            mk.definition('OBJECTS', '$(OBJECTS1) gcmaptable.s')
 
-                    lblofiles.append(ofile)
-                mk.definition('ASMLBLOBJFILES', lblofiles)
-                mk.definition('OBJECTS', 'gcmaptable.obj $(ASMLBLOBJFILES)')
-                # /Oi (enable intrinsics) and /Ob1 (some inlining) are mandatory
-                # even in debug builds
-                mk.definition('ASM_CFLAGS', '$(CFLAGS) $(CFLAGSEXTRA) /Oi /Ob1')
-                mk.rule('.SUFFIXES', '.s', [])
-                mk.rule('.s.obj', '',
-                        'cmd /c $(MASM) /nologo /Cx /Cp /Zm /coff /Fo$@ /c $< $(INCLUDEDIRS)')
-                mk.rule('.c.gcmap', '',
-                        ['$(CC) /nologo $(ASM_CFLAGS) /c /FAs /Fa$*.s $< $(INCLUDEDIRS)',
-                         'cmd /c $(PYTHON) $(RPYDIR)/translator/c/gcc/trackgcroot.py -fmsvc -t $*.s > $@']
-                        )
-                mk.rule('gcmaptable.c', '$(GCMAPFILES)',
-                        'cmd /c $(PYTHON) $(RPYDIR)/translator/c/gcc/trackgcroot.py -fmsvc $(GCMAPFILES) > $@')
+            # the rule that transforms %.c into %.o, by compiling it to
+            # %.s, then applying trackgcroot to get %.lbl.s and %.gcmap, and
+            # finally by using the assembler ($(CC) again for now) to get %.o
+            mk.rule('%.o %.gcmap', '%.c', [
+                '$(CC) $(CFLAGS) $(CFLAGSEXTRA) -frandom-seed=$< '
+                    '-o $*.s -S $< $(INCLUDEDIRS)',
+                '$(PYTHON) $(RPYDIR)/translator/c/gcc/trackgcroot.py '
+                    '-t $*.s > $*.gctmp',
+                '$(CC) -o $*.o -c $*.lbl.s',
+                'mv $*.gctmp $*.gcmap',
+                'rm $*.s $*.lbl.s'])
 
-            else:
-                mk.definition('OBJECTS', '$(ASMLBLFILES) gcmaptable.s')
-                mk.rule('%.s', '%.c', '$(CC) $(CFLAGS) $(CFLAGSEXTRA) -frandom-seed=$< -o $@ -S $< $(INCLUDEDIRS)')
-                mk.rule('%.s', '%.cxx', '$(CXX) $(CFLAGS) $(CFLAGSEXTRA) -frandom-seed=$< -o $@ -S $< $(INCLUDEDIRS)')
-                mk.rule('%.lbl.s %.gcmap', '%.s',
-                        [
-                             '$(PYTHON) $(RPYDIR)/translator/c/gcc/trackgcroot.py '
-                             '-t $< > $*.gctmp',
-                         'mv $*.gctmp $*.gcmap'])
-                mk.rule('gcmaptable.s', '$(GCMAPFILES)',
-                        [
-                             '$(PYTHON) $(RPYDIR)/translator/c/gcc/trackgcroot.py '
-                             '$(GCMAPFILES) > $@.tmp',
-                         'mv $@.tmp $@'])
-                mk.rule('.PRECIOUS', '%.s', "# don't remove .s files if Ctrl-C'ed")
+            # the rule to compute gcmaptable.s
+            mk.rule('gcmaptable.s', '$(GCMAPFILES)',
+                    [
+                         '$(PYTHON) $(RPYDIR)/translator/c/gcc/trackgcroot.py '
+                         '$(GCMAPFILES) > $@.tmp',
+                     'mv $@.tmp $@'])
 
         else:
             if self.translator.platform.name == 'msvc':

rpython/translator/c/test/test_newgc.py

             #
             fd1 = os.open(filename1, os.O_WRONLY | os.O_CREAT, 0666)
             fd2 = os.open(filename2, os.O_WRONLY | os.O_CREAT, 0666)
+            # try to ensure we get twice the exact same output below
+            gc.collect(); gc.collect(); gc.collect()
             rgc.dump_rpy_heap(fd1)
             rgc.dump_rpy_heap(fd2)      # try twice in a row
             keepalive_until_here(s2)