Author: Richard Plangger <planri...@gmail.com>
Branch: new-jit-log
Changeset: r84476:883a1b184337
Date: 2016-05-16 11:11 +0200
http://bitbucket.org/pypy/pypy/changeset/883a1b184337/

Log:    merged default

diff --git a/lib-python/2.7/test/test_sys_settrace.py 
b/lib-python/2.7/test/test_sys_settrace.py
--- a/lib-python/2.7/test/test_sys_settrace.py
+++ b/lib-python/2.7/test/test_sys_settrace.py
@@ -328,8 +328,8 @@
 
     def test_13_genexp(self):
         if self.using_gc:
+            gc.enable()
             test_support.gc_collect()
-            gc.enable()
         try:
             self.run_test(generator_example)
             # issue1265: if the trace function contains a generator,
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
@@ -89,3 +89,19 @@
 Use the new rgc.FinalizerQueue mechanism to clean up the handling of
 ``__del__`` methods.  Fixes notably issue #2287.  (All RPython
 subclasses of W_Root need to use FinalizerQueue now.)
+
+.. branch: ufunc-outer
+
+Implement ufunc.outer on numpypy
+
+.. branch: verbose-imports
+
+Support ``pypy -v``: verbose imports.  It does not log as much as
+cpython, but it should be enough to help when debugging package layout
+problems.
+
+.. branch: cpyext-macros-cast
+
+Fix some warnings when compiling CPython C extension modules
+
+.. branch: syntax_fix
diff --git a/pypy/interpreter/app_main.py b/pypy/interpreter/app_main.py
--- a/pypy/interpreter/app_main.py
+++ b/pypy/interpreter/app_main.py
@@ -2,7 +2,7 @@
 # This is pure Python code that handles the main entry point into "pypy".
 # See test/test_app_main.
 
-# Missing vs CPython: -d, -t, -v, -x, -3
+# Missing vs CPython: -d, -t, -x, -3
 USAGE1 = __doc__ = """\
 Options and arguments (and corresponding environment variables):
 -B     : don't write .py[co] files on import; also PYTHONDONTWRITEBYTECODE=x
@@ -19,6 +19,8 @@
 -s     : don't add user site directory to sys.path; also PYTHONNOUSERSITE
 -S     : don't imply 'import site' on initialization
 -u     : unbuffered binary stdout and stderr; also PYTHONUNBUFFERED=x
+-v     : verbose (trace import statements); also PYTHONVERBOSE=x
+         can be supplied multiple times to increase verbosity
 -V     : print the Python version number and exit (also --version)
 -W arg : warning control; arg is action:message:category:module:lineno
          also PYTHONWARNINGS=arg
@@ -529,6 +531,7 @@
                      warnoptions,
                      unbuffered,
                      ignore_environment,
+                     verbose,
                      **ignored):
     # with PyPy in top of CPython we can only have around 100
     # but we need more in the translated PyPy for the compiler package
@@ -663,6 +666,8 @@
                 inspect = True
             else:
                 # If not interactive, just read and execute stdin normally.
+                if verbose:
+                    print_banner(not no_site)
                 @hidden_applevel
                 def run_it():
                     co_stdin = compile(sys.stdin.read(), '<stdin>', 'exec',
@@ -724,10 +729,10 @@
     return status
 
 def print_banner(copyright):
-    print 'Python %s on %s' % (sys.version, sys.platform)
+    print >> sys.stderr, 'Python %s on %s' % (sys.version, sys.platform)
     if copyright:
-        print ('Type "help", "copyright", "credits" or '
-               '"license" for more information.')
+        print >> sys.stderr, ('Type "help", "copyright", "credits" or '
+                              '"license" for more information.')
 
 STDLIB_WARNING = """\
 debug: WARNING: Library path not found, using compiled-in sys.path.
diff --git a/pypy/interpreter/executioncontext.py 
b/pypy/interpreter/executioncontext.py
--- a/pypy/interpreter/executioncontext.py
+++ b/pypy/interpreter/executioncontext.py
@@ -466,6 +466,13 @@
             list = self.fired_actions
             if list is not None:
                 self.fired_actions = None
+                # NB. in case there are several actions, we reset each
+                # 'action._fired' to false only when we're about to call
+                # 'action.perform()'.  This means that if
+                # 'action.fire()' happens to be called any time before
+                # the corresponding perform(), the fire() has no
+                # effect---which is the effect we want, because
+                # perform() will be called anyway.
                 for action in list:
                     action._fired = False
                     action.perform(ec, frame)
diff --git a/pypy/module/__pypy__/interp_magic.py 
b/pypy/module/__pypy__/interp_magic.py
--- a/pypy/module/__pypy__/interp_magic.py
+++ b/pypy/module/__pypy__/interp_magic.py
@@ -51,6 +51,11 @@
                            space.newint(cache.misses.get(name, 0))])
 
 def builtinify(space, w_func):
+    """To implement at app-level modules that are, in CPython,
+    implemented in C: this decorator protects a function from being ever
+    bound like a method.  Useful because some tests do things like put
+    a "built-in" function on a class and access it via the instance.
+    """
     from pypy.interpreter.function import Function, BuiltinFunction
     func = space.interp_w(Function, w_func)
     bltn = BuiltinFunction(func)
diff --git a/pypy/module/_winreg/interp_winreg.py 
b/pypy/module/_winreg/interp_winreg.py
--- a/pypy/module/_winreg/interp_winreg.py
+++ b/pypy/module/_winreg/interp_winreg.py
@@ -14,11 +14,13 @@
                                          space.wrap(message)]))
 
 class W_HKEY(W_Root):
-    def __init__(self, hkey):
+    def __init__(self, space, hkey):
         self.hkey = hkey
+        self.space = space
+        self.register_finalizer(space)
 
-    def descr_del(self, space):
-        self.Close(space)
+    def _finalize_(self):
+        self.Close(self.space)
 
     def as_int(self):
         return rffi.cast(rffi.SIZE_T, self.hkey)
@@ -64,7 +66,7 @@
 @unwrap_spec(key=int)
 def new_HKEY(space, w_subtype, key):
     hkey = rffi.cast(rwinreg.HKEY, key)
-    return space.wrap(W_HKEY(hkey))
+    return space.wrap(W_HKEY(space, hkey))
 descr_HKEY_new = interp2app(new_HKEY)
 
 W_HKEY.typedef = TypeDef(
@@ -91,7 +93,6 @@
 __int__ - Converting a handle to an integer returns the Win32 handle.
 __cmp__ - Handle objects are compared using the handle value.""",
     __new__ = descr_HKEY_new,
-    __del__ = interp2app(W_HKEY.descr_del),
     __repr__ = interp2app(W_HKEY.descr_repr),
     __int__ = interp2app(W_HKEY.descr_int),
     __nonzero__ = interp2app(W_HKEY.descr_nonzero),
@@ -480,7 +481,7 @@
         ret = rwinreg.RegCreateKey(hkey, subkey, rethkey)
         if ret != 0:
             raiseWindowsError(space, ret, 'CreateKey')
-        return space.wrap(W_HKEY(rethkey[0]))
+        return space.wrap(W_HKEY(space, rethkey[0]))
 
 @unwrap_spec(subkey=str, res=int, sam=rffi.r_uint)
 def CreateKeyEx(space, w_hkey, subkey, res=0, sam=rwinreg.KEY_WRITE):
@@ -502,7 +503,7 @@
                                      lltype.nullptr(rwin32.LPDWORD.TO))
         if ret != 0:
             raiseWindowsError(space, ret, 'CreateKeyEx')
-        return space.wrap(W_HKEY(rethkey[0]))
+        return space.wrap(W_HKEY(space, rethkey[0]))
 
 @unwrap_spec(subkey=str)
 def DeleteKey(space, w_hkey, subkey):
@@ -549,7 +550,7 @@
         ret = rwinreg.RegOpenKeyEx(hkey, subkey, res, sam, rethkey)
         if ret != 0:
             raiseWindowsError(space, ret, 'RegOpenKeyEx')
-        return space.wrap(W_HKEY(rethkey[0]))
+        return space.wrap(W_HKEY(space, rethkey[0]))
 
 @unwrap_spec(index=int)
 def EnumValue(space, w_hkey, index):
@@ -688,7 +689,7 @@
         ret = rwinreg.RegConnectRegistry(machine, hkey, rethkey)
         if ret != 0:
             raiseWindowsError(space, ret, 'RegConnectRegistry')
-        return space.wrap(W_HKEY(rethkey[0]))
+        return space.wrap(W_HKEY(space, rethkey[0]))
 
 @unwrap_spec(source=unicode)
 def ExpandEnvironmentStrings(space, source):
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -203,46 +203,46 @@
 # id.  Invariant: this variable always contain 0 when the PyPy GIL is
 # released.  It should also contain 0 when regular RPython code
 # executes.  In non-cpyext-related code, it will thus always be 0.
-# 
+#
 # **make_generic_cpy_call():** RPython to C, with the GIL held.  Before
 # the call, must assert that the global variable is 0 and set the
 # current thread identifier into the global variable.  After the call,
 # assert that the global variable still contains the current thread id,
 # and reset it to 0.
-# 
+#
 # **make_wrapper():** C to RPython; by default assume that the GIL is
 # held, but accepts gil="acquire", "release", "around",
 # "pygilstate_ensure", "pygilstate_release".
-# 
+#
 # When a wrapper() is called:
-# 
+#
 # * "acquire": assert that the GIL is not currently held, i.e. the
 #   global variable does not contain the current thread id (otherwise,
 #   deadlock!).  Acquire the PyPy GIL.  After we acquired it, assert
 #   that the global variable is 0 (it must be 0 according to the
 #   invariant that it was 0 immediately before we acquired the GIL,
 #   because the GIL was released at that point).
-# 
+#
 # * gil=None: we hold the GIL already.  Assert that the current thread
 #   identifier is in the global variable, and replace it with 0.
-# 
+#
 # * "pygilstate_ensure": if the global variable contains the current
 #   thread id, replace it with 0 and set the extra arg to 0.  Otherwise,
 #   do the "acquire" and set the extra arg to 1.  Then we'll call
 #   pystate.py:PyGILState_Ensure() with this extra arg, which will do
 #   the rest of the logic.
-# 
+#
 # When a wrapper() returns, first assert that the global variable is
 # still 0, and then:
-# 
+#
 # * "release": release the PyPy GIL.  The global variable was 0 up to
 #   and including at the point where we released the GIL, but afterwards
 #   it is possible that the GIL is acquired by a different thread very
 #   quickly.
-# 
+#
 # * gil=None: we keep holding the GIL.  Set the current thread
 #   identifier into the global variable.
-# 
+#
 # * "pygilstate_release": if the argument is PyGILState_UNLOCKED,
 #   release the PyPy GIL; otherwise, set the current thread identifier
 #   into the global variable.  The rest of the logic of
@@ -254,7 +254,7 @@
 
 cpyext_namespace = NameManager('cpyext_')
 
-class ApiFunction:
+class ApiFunction(object):
     def __init__(self, argtypes, restype, callable, error=_NOT_SPECIFIED,
                  c_name=None, gil=None, result_borrowed=False, 
result_is_ll=False):
         self.argtypes = argtypes
@@ -292,11 +292,48 @@
     def get_wrapper(self, space):
         wrapper = getattr(self, '_wrapper', None)
         if wrapper is None:
-            wrapper = make_wrapper(space, self.callable, self.gil)
-            self._wrapper = wrapper
-            wrapper.relax_sig_check = True
-            if self.c_name is not None:
-                wrapper.c_name = cpyext_namespace.uniquename(self.c_name)
+            wrapper = self._wrapper = self._make_wrapper(space)
+        return wrapper
+
+    # Make the wrapper for the cases (1) and (2)
+    def _make_wrapper(self, space):
+        "NOT_RPYTHON"
+        # This logic is obscure, because we try to avoid creating one
+        # big wrapper() function for every callable.  Instead we create
+        # only one per "signature".
+
+        argtypesw = zip(self.argtypes,
+                        [_name.startswith("w_") for _name in self.argnames])
+        error_value = getattr(self, "error_value", CANNOT_FAIL)
+        if (isinstance(self.restype, lltype.Ptr)
+                and error_value is not CANNOT_FAIL):
+            assert lltype.typeOf(error_value) == self.restype
+            assert not error_value    # only support error=NULL
+            error_value = 0    # because NULL is not hashable
+
+        if self.result_is_ll:
+            result_kind = "L"
+        elif self.result_borrowed:
+            result_kind = "B"     # note: 'result_borrowed' is ignored if we 
also
+        else:                     #  say 'result_is_ll=True' (in this case it's
+            result_kind = "."     #  up to you to handle refcounting anyway)
+
+        signature = (tuple(argtypesw),
+                    self.restype,
+                    result_kind,
+                    error_value,
+                    self.gil)
+
+        cache = space.fromcache(WrapperCache)
+        try:
+            wrapper_gen = cache.wrapper_gens[signature]
+        except KeyError:
+            wrapper_gen = WrapperGen(space, signature)
+            cache.wrapper_gens[signature] = wrapper_gen
+        wrapper = wrapper_gen.make_wrapper(self.callable)
+        wrapper.relax_sig_check = True
+        if self.c_name is not None:
+            wrapper.c_name = cpyext_namespace.uniquename(self.c_name)
         return wrapper
 
 DEFAULT_HEADER = 'pypy_decl.h'
@@ -373,7 +410,16 @@
                             arg = rffi.cast(ARG, as_pyobj(space, input_arg))
                         else:
                             arg = rffi.cast(ARG, input_arg)
-                    elif is_PyObject(ARG) and is_wrapped:
+                    elif ARG == rffi.VOIDP and not is_wrapped:
+                        # unlike is_PyObject case above, we allow any kind of
+                        # argument -- just, if it's an object, we assume the
+                        # caller meant for it to become a PyObject*.
+                        if input_arg is None or isinstance(input_arg, W_Root):
+                            keepalives += (input_arg,)
+                            arg = rffi.cast(ARG, as_pyobj(space, input_arg))
+                        else:
+                            arg = rffi.cast(ARG, input_arg)
+                    elif (is_PyObject(ARG) or ARG == rffi.VOIDP) and 
is_wrapped:
                         # build a W_Root, possibly from a 'PyObject *'
                         if is_pyobj(input_arg):
                             arg = from_ref(space, input_arg)
@@ -683,7 +729,6 @@
     def __init__(self, space):
         self.space = space
         self.wrapper_gens = {}    # {signature: WrapperGen()}
-        self.stats = [0, 0]
 
 class WrapperGen(object):
     wrapper_second_level = None
@@ -691,66 +736,22 @@
     def __init__(self, space, signature):
         self.space = space
         self.signature = signature
-        self.callable2name = []
 
     def make_wrapper(self, callable):
-        self.callable2name.append((callable, callable.__name__))
         if self.wrapper_second_level is None:
             self.wrapper_second_level = make_wrapper_second_level(
-                self.space, self.callable2name, *self.signature)
+                self.space, *self.signature)
         wrapper_second_level = self.wrapper_second_level
 
+        name = callable.__name__
         def wrapper(*args):
             # no GC here, not even any GC object
-            args += (callable,)
-            return wrapper_second_level(*args)
+            return wrapper_second_level(callable, name, *args)
 
         wrapper.__name__ = "wrapper for %r" % (callable, )
         return wrapper
 
 
-# Make the wrapper for the cases (1) and (2)
-def make_wrapper(space, callable, gil=None):
-    "NOT_RPYTHON"
-    # This logic is obscure, because we try to avoid creating one
-    # big wrapper() function for every callable.  Instead we create
-    # only one per "signature".
-
-    argnames = callable.api_func.argnames
-    argtypesw = zip(callable.api_func.argtypes,
-                    [_name.startswith("w_") for _name in argnames])
-    error_value = getattr(callable.api_func, "error_value", CANNOT_FAIL)
-    if (isinstance(callable.api_func.restype, lltype.Ptr)
-            and error_value is not CANNOT_FAIL):
-        assert lltype.typeOf(error_value) == callable.api_func.restype
-        assert not error_value    # only support error=NULL
-        error_value = 0    # because NULL is not hashable
-
-    if callable.api_func.result_is_ll:
-        result_kind = "L"
-    elif callable.api_func.result_borrowed:
-        result_kind = "B"     # note: 'result_borrowed' is ignored if we also
-    else:                     #  say 'result_is_ll=True' (in this case it's
-        result_kind = "."     #  up to you to handle refcounting anyway)
-
-    signature = (tuple(argtypesw),
-                 callable.api_func.restype,
-                 result_kind,
-                 error_value,
-                 gil)
-
-    cache = space.fromcache(WrapperCache)
-    cache.stats[1] += 1
-    try:
-        wrapper_gen = cache.wrapper_gens[signature]
-    except KeyError:
-        #print signature
-        wrapper_gen = cache.wrapper_gens[signature] = WrapperGen(space,
-                                                                 signature)
-        cache.stats[0] += 1
-    #print 'Wrapper cache [wrappers/total]:', cache.stats
-    return wrapper_gen.make_wrapper(callable)
-
 
 @dont_inline
 def deadlock_error(funcname):
@@ -784,7 +785,7 @@
         pypy_debug_catch_fatal_exception()
         assert False
 
-def make_wrapper_second_level(space, callable2name, argtypesw, restype,
+def make_wrapper_second_level(space, argtypesw, restype,
                               result_kind, error_value, gil):
     from rpython.rlib import rgil
     argtypes_enum_ui = unrolling_iterable(enumerate(argtypesw))
@@ -807,29 +808,20 @@
     def invalid(err):
         "NOT_RPYTHON: translation-time crash if this ends up being called"
         raise ValueError(err)
-    invalid.__name__ = 'invalid_%s' % (callable2name[0][1],)
+    invalid.__name__ = 'invalid_%s' % name
 
-    def nameof(callable):
-        for c, n in callable2name:
-            if c is callable:
-                return n
-        return '<unknown function>'
-    nameof._dont_inline_ = True
-
-    def wrapper_second_level(*args):
+    def wrapper_second_level(callable, name, *args):
         from pypy.module.cpyext.pyobject import make_ref, from_ref, is_pyobj
         from pypy.module.cpyext.pyobject import as_pyobj
         # we hope that malloc removal removes the newtuple() that is
         # inserted exactly here by the varargs specializer
-        callable = args[-1]
-        args = args[:-1]
 
         # see "Handling of the GIL" above (careful, we don't have the GIL here)
         tid = rthread.get_or_make_ident()
         _gil_auto = (gil_auto_workaround and cpyext_glob_tid_ptr[0] != tid)
         if gil_acquire or _gil_auto:
             if cpyext_glob_tid_ptr[0] == tid:
-                deadlock_error(nameof(callable))
+                deadlock_error(name)
             rgil.acquire()
             assert cpyext_glob_tid_ptr[0] == 0
         elif pygilstate_ensure:
@@ -842,7 +834,7 @@
                 args += (pystate.PyGILState_UNLOCKED,)
         else:
             if cpyext_glob_tid_ptr[0] != tid:
-                no_gil_error(nameof(callable))
+                no_gil_error(name)
             cpyext_glob_tid_ptr[0] = 0
 
         rffi.stackcounter.stacks_counter += 1
@@ -859,6 +851,10 @@
                 if is_PyObject(typ) and is_wrapped:
                     assert is_pyobj(arg)
                     arg_conv = from_ref(space, rffi.cast(PyObject, arg))
+                elif typ == rffi.VOIDP and is_wrapped:
+                    # Many macros accept a void* so that one can pass a
+                    # PyObject* or a PySomeSubtype*.
+                    arg_conv = from_ref(space, rffi.cast(PyObject, arg))
                 else:
                     arg_conv = arg
                 boxed_args += (arg_conv, )
@@ -888,7 +884,7 @@
 
             if failed:
                 if error_value is CANNOT_FAIL:
-                    raise not_supposed_to_fail(nameof(callable))
+                    raise not_supposed_to_fail(name)
                 retval = error_value
 
             elif is_PyObject(restype):
@@ -908,7 +904,7 @@
                 retval = rffi.cast(restype, result)
 
         except Exception as e:
-            unexpected_exception(nameof(callable), e, tb)
+            unexpected_exception(name, e, tb)
             return fatal_value
 
         assert lltype.typeOf(retval) == restype
@@ -1019,7 +1015,7 @@
     structindex = {}
     for header, header_functions in FUNCTIONS_BY_HEADER.iteritems():
         for name, func in header_functions.iteritems():
-            if not func: 
+            if not func:
                 # added only for the macro, not the decl
                 continue
             restype, args = c_function_signature(db, func)
@@ -1033,7 +1029,7 @@
     RPY_EXTERN struct PyPyAPI* pypyAPI = &_pypyAPI;
     """ % dict(members=structmembers)
 
-    functions = generate_decls_and_callbacks(db, export_symbols, 
+    functions = generate_decls_and_callbacks(db, export_symbols,
                                             prefix='cpyexttest')
 
     global_objects = []
@@ -1415,7 +1411,7 @@
 
     generate_macros(export_symbols, prefix=prefix)
 
-    functions = generate_decls_and_callbacks(db, [], api_struct=False, 
+    functions = generate_decls_and_callbacks(db, [], api_struct=False,
                                             prefix=prefix)
     code = "#include <Python.h>\n"
     if use_micronumpy:
@@ -1471,7 +1467,7 @@
             if not func:
                 continue
             newname = mangle_name('PyPy', name) or name
-            deco = entrypoint_lowlevel("cpyext", func.argtypes, newname, 
+            deco = entrypoint_lowlevel("cpyext", func.argtypes, newname,
                                         relax=True)
             deco(func.get_wrapper(space))
 
diff --git a/pypy/module/cpyext/cdatetime.py b/pypy/module/cpyext/cdatetime.py
--- a/pypy/module/cpyext/cdatetime.py
+++ b/pypy/module/cpyext/cdatetime.py
@@ -178,67 +178,67 @@
 
 # Accessors
 
-@cpython_api([PyDateTime_Date], rffi.INT_real, error=CANNOT_FAIL)
+@cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL)
 def PyDateTime_GET_YEAR(space, w_obj):
     """Return the year, as a positive int.
     """
     return space.int_w(space.getattr(w_obj, space.wrap("year")))
 
-@cpython_api([PyDateTime_Date], rffi.INT_real, error=CANNOT_FAIL)
+@cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL)
 def PyDateTime_GET_MONTH(space, w_obj):
     """Return the month, as an int from 1 through 12.
     """
     return space.int_w(space.getattr(w_obj, space.wrap("month")))
 
-@cpython_api([PyDateTime_Date], rffi.INT_real, error=CANNOT_FAIL)
+@cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL)
 def PyDateTime_GET_DAY(space, w_obj):
     """Return the day, as an int from 1 through 31.
     """
     return space.int_w(space.getattr(w_obj, space.wrap("day")))
 
-@cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL)
+@cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL)
 def PyDateTime_DATE_GET_HOUR(space, w_obj):
     """Return the hour, as an int from 0 through 23.
     """
     return space.int_w(space.getattr(w_obj, space.wrap("hour")))
 
-@cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL)
+@cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL)
 def PyDateTime_DATE_GET_MINUTE(space, w_obj):
     """Return the minute, as an int from 0 through 59.
     """
     return space.int_w(space.getattr(w_obj, space.wrap("minute")))
 
-@cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL)
+@cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL)
 def PyDateTime_DATE_GET_SECOND(space, w_obj):
     """Return the second, as an int from 0 through 59.
     """
     return space.int_w(space.getattr(w_obj, space.wrap("second")))
 
-@cpython_api([PyDateTime_DateTime], rffi.INT_real, error=CANNOT_FAIL)
+@cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL)
 def PyDateTime_DATE_GET_MICROSECOND(space, w_obj):
     """Return the microsecond, as an int from 0 through 999999.
     """
     return space.int_w(space.getattr(w_obj, space.wrap("microsecond")))
 
-@cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL)
+@cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL)
 def PyDateTime_TIME_GET_HOUR(space, w_obj):
     """Return the hour, as an int from 0 through 23.
     """
     return space.int_w(space.getattr(w_obj, space.wrap("hour")))
 
-@cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL)
+@cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL)
 def PyDateTime_TIME_GET_MINUTE(space, w_obj):
     """Return the minute, as an int from 0 through 59.
     """
     return space.int_w(space.getattr(w_obj, space.wrap("minute")))
 
-@cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL)
+@cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL)
 def PyDateTime_TIME_GET_SECOND(space, w_obj):
     """Return the second, as an int from 0 through 59.
     """
     return space.int_w(space.getattr(w_obj, space.wrap("second")))
 
-@cpython_api([PyDateTime_Time], rffi.INT_real, error=CANNOT_FAIL)
+@cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL)
 def PyDateTime_TIME_GET_MICROSECOND(space, w_obj):
     """Return the microsecond, as an int from 0 through 999999.
     """
@@ -248,14 +248,14 @@
 # But it does not seem possible to expose a different structure
 # for types defined in a python module like lib/datetime.py.
 
-@cpython_api([PyDateTime_Delta], rffi.INT_real, error=CANNOT_FAIL)
+@cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL)
 def PyDateTime_DELTA_GET_DAYS(space, w_obj):
     return space.int_w(space.getattr(w_obj, space.wrap("days")))
 
-@cpython_api([PyDateTime_Delta], rffi.INT_real, error=CANNOT_FAIL)
+@cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL)
 def PyDateTime_DELTA_GET_SECONDS(space, w_obj):
     return space.int_w(space.getattr(w_obj, space.wrap("seconds")))
 
-@cpython_api([PyDateTime_Delta], rffi.INT_real, error=CANNOT_FAIL)
+@cpython_api([rffi.VOIDP], rffi.INT_real, error=CANNOT_FAIL)
 def PyDateTime_DELTA_GET_MICROSECONDS(space, w_obj):
     return space.int_w(space.getattr(w_obj, space.wrap("microseconds")))
diff --git a/pypy/module/cpyext/floatobject.py 
b/pypy/module/cpyext/floatobject.py
--- a/pypy/module/cpyext/floatobject.py
+++ b/pypy/module/cpyext/floatobject.py
@@ -48,7 +48,7 @@
 def PyFloat_AsDouble(space, w_obj):
     return space.float_w(space.float(w_obj))
 
-@cpython_api([PyObject], lltype.Float, error=CANNOT_FAIL)
+@cpython_api([rffi.VOIDP], lltype.Float, error=CANNOT_FAIL)
 def PyFloat_AS_DOUBLE(space, w_float):
     """Return a C double representation of the contents of w_float, but
     without error checking."""
diff --git a/pypy/module/cpyext/include/listobject.h 
b/pypy/module/cpyext/include/listobject.h
--- a/pypy/module/cpyext/include/listobject.h
+++ b/pypy/module/cpyext/include/listobject.h
@@ -1,1 +1,1 @@
-#define PyList_GET_ITEM PyList_GetItem
+#define PyList_GET_ITEM(o, i) PyList_GetItem((PyObject*)(o), (i))
diff --git a/pypy/module/cpyext/intobject.py b/pypy/module/cpyext/intobject.py
--- a/pypy/module/cpyext/intobject.py
+++ b/pypy/module/cpyext/intobject.py
@@ -104,7 +104,7 @@
         num = space.bigint_w(w_int)
         return num.ulonglongmask()
 
-@cpython_api([PyObject], lltype.Signed, error=CANNOT_FAIL)
+@cpython_api([rffi.VOIDP], lltype.Signed, error=CANNOT_FAIL)
 def PyInt_AS_LONG(space, w_int):
     """Return the value of the object w_int. No error checking is performed."""
     return space.int_w(w_int)
diff --git a/pypy/module/cpyext/listobject.py b/pypy/module/cpyext/listobject.py
--- a/pypy/module/cpyext/listobject.py
+++ b/pypy/module/cpyext/listobject.py
@@ -21,7 +21,7 @@
     """
     return space.newlist([None] * len)
 
-@cpython_api([PyObject, Py_ssize_t, PyObject], PyObject, error=CANNOT_FAIL,
+@cpython_api([rffi.VOIDP, Py_ssize_t, PyObject], PyObject, error=CANNOT_FAIL,
              result_borrowed=True)
 def PyList_SET_ITEM(space, w_list, index, w_item):
     """Macro form of PyList_SetItem() without error checking. This is normally
@@ -87,7 +87,7 @@
     space.call_method(space.w_list, "insert", w_list, space.wrap(index), 
w_item)
     return 0
 
-@cpython_api([PyObject], Py_ssize_t, error=CANNOT_FAIL)
+@cpython_api([rffi.VOIDP], Py_ssize_t, error=CANNOT_FAIL)
 def PyList_GET_SIZE(space, w_list):
     """Macro form of PyList_Size() without error checking.
     """
diff --git a/pypy/module/cpyext/sequence.py b/pypy/module/cpyext/sequence.py
--- a/pypy/module/cpyext/sequence.py
+++ b/pypy/module/cpyext/sequence.py
@@ -54,7 +54,7 @@
     except OperationError:
         raise OperationError(space.w_TypeError, space.wrap(rffi.charp2str(m)))
 
-@cpython_api([PyObject, Py_ssize_t], PyObject, result_borrowed=True)
+@cpython_api([rffi.VOIDP, Py_ssize_t], PyObject, result_borrowed=True)
 def PySequence_Fast_GET_ITEM(space, w_obj, index):
     """Return the ith element of o, assuming that o was returned by
     PySequence_Fast(), o is not NULL, and that i is within bounds.
@@ -67,7 +67,7 @@
                 "PySequence_Fast_GET_ITEM called but object is not a list or "
                 "sequence")
 
-@cpython_api([PyObject], Py_ssize_t, error=CANNOT_FAIL)
+@cpython_api([rffi.VOIDP], Py_ssize_t, error=CANNOT_FAIL)
 def PySequence_Fast_GET_SIZE(space, w_obj):
     """Returns the length of o, assuming that o was returned by
     PySequence_Fast() and that o is not NULL.  The size can also be
@@ -82,7 +82,7 @@
                 "PySequence_Fast_GET_SIZE called but object is not a list or "
                 "sequence")
 
-@cpython_api([PyObject], PyObjectP)
+@cpython_api([rffi.VOIDP], PyObjectP)
 def PySequence_Fast_ITEMS(space, w_obj):
     """Return the underlying array of PyObject pointers.  Assumes that o was 
returned
     by PySequence_Fast() and o is not NULL.
@@ -119,7 +119,7 @@
     space.delslice(w_obj, space.wrap(start), space.wrap(end))
     return 0
 
-@cpython_api([PyObject, Py_ssize_t], PyObject)
+@cpython_api([rffi.VOIDP, Py_ssize_t], PyObject)
 def PySequence_ITEM(space, w_obj, i):
     """Return the ith element of o or NULL on failure. Macro form of
     PySequence_GetItem() but without checking that
diff --git a/pypy/module/cpyext/setobject.py b/pypy/module/cpyext/setobject.py
--- a/pypy/module/cpyext/setobject.py
+++ b/pypy/module/cpyext/setobject.py
@@ -74,7 +74,7 @@
     space.call_method(space.w_set, 'clear', w_set)
     return 0
 
-@cpython_api([PyObject], Py_ssize_t, error=CANNOT_FAIL)
+@cpython_api([rffi.VOIDP], Py_ssize_t, error=CANNOT_FAIL)
 def PySet_GET_SIZE(space, w_s):
     """Macro form of PySet_Size() without error checking."""
     return space.int_w(space.len(w_s))
diff --git a/pypy/module/cpyext/test/test_bytesobject.py 
b/pypy/module/cpyext/test/test_bytesobject.py
--- a/pypy/module/cpyext/test/test_bytesobject.py
+++ b/pypy/module/cpyext/test/test_bytesobject.py
@@ -288,6 +288,24 @@
         # This does not test much, but at least the refcounts are checked.
         assert module.test_intern_inplace('s') == 's'
 
+    def test_bytes_macros(self):
+        """The PyString_* macros cast, and calls expecting that build."""
+        module = self.import_extension('foo', [
+             ("test_macro_invocations", "METH_NOARGS",
+             """
+                PyObject* o = PyString_FromString("");
+                PyStringObject* u = (PyStringObject*)o;
+
+                PyString_GET_SIZE(u);
+                PyString_GET_SIZE(o);
+
+                PyString_AS_STRING(o);
+                PyString_AS_STRING(u);
+
+                return o;
+             """)])
+        assert module.test_macro_invocations() == ''
+
     def test_hash_and_state(self):
         module = self.import_extension('foo', [
             ("test_hash", "METH_VARARGS",
diff --git a/pypy/module/cpyext/test/test_datetime.py 
b/pypy/module/cpyext/test/test_datetime.py
--- a/pypy/module/cpyext/test/test_datetime.py
+++ b/pypy/module/cpyext/test/test_datetime.py
@@ -117,3 +117,106 @@
                                       datetime.timedelta,
                                       datetime.tzinfo)
         module.clear_types()
+
+    def test_macros(self):
+        module = self.import_extension('foo', [
+            ("test_date_macros", "METH_NOARGS",
+             """
+                 PyDateTime_IMPORT;
+                 if (!PyDateTimeAPI) {
+                     PyErr_SetString(PyExc_RuntimeError, "No PyDateTimeAPI");
+                     return NULL;
+                 }
+                 PyObject* obj = PyDate_FromDate(2000, 6, 6);
+                 PyDateTime_Date* d = (PyDateTime_Date*)obj;
+
+                 PyDateTime_GET_YEAR(obj);
+                 PyDateTime_GET_YEAR(d);
+
+                 PyDateTime_GET_MONTH(obj);
+                 PyDateTime_GET_MONTH(d);
+
+                 PyDateTime_GET_DAY(obj);
+                 PyDateTime_GET_DAY(d);
+
+                 return obj;
+             """),
+            ("test_datetime_macros", "METH_NOARGS",
+             """
+                 PyDateTime_IMPORT;
+                 if (!PyDateTimeAPI) {
+                     PyErr_SetString(PyExc_RuntimeError, "No PyDateTimeAPI");
+                     return NULL;
+                 }
+                 PyObject* obj = PyDateTime_FromDateAndTime(2000, 6, 6, 6, 6, 
6, 6);
+                 PyDateTime_DateTime* dt = (PyDateTime_DateTime*)obj;
+
+                 PyDateTime_GET_YEAR(obj);
+                 PyDateTime_GET_YEAR(dt);
+
+                 PyDateTime_GET_MONTH(obj);
+                 PyDateTime_GET_MONTH(dt);
+
+                 PyDateTime_GET_DAY(obj);
+                 PyDateTime_GET_DAY(dt);
+
+                 PyDateTime_DATE_GET_HOUR(obj);
+                 PyDateTime_DATE_GET_HOUR(dt);
+
+                 PyDateTime_DATE_GET_MINUTE(obj);
+                 PyDateTime_DATE_GET_MINUTE(dt);
+
+                 PyDateTime_DATE_GET_SECOND(obj);
+                 PyDateTime_DATE_GET_SECOND(dt);
+
+                 PyDateTime_DATE_GET_MICROSECOND(obj);
+                 PyDateTime_DATE_GET_MICROSECOND(dt);
+
+                 return obj;
+             """),
+            ("test_time_macros", "METH_NOARGS",
+             """
+                 PyDateTime_IMPORT;
+                 if (!PyDateTimeAPI) {
+                     PyErr_SetString(PyExc_RuntimeError, "No PyDateTimeAPI");
+                     return NULL;
+                 }
+                 PyObject* obj = PyTime_FromTime(6, 6, 6, 6);
+                 PyDateTime_Time* t = (PyDateTime_Time*)obj;
+
+                 PyDateTime_TIME_GET_HOUR(obj);
+                 PyDateTime_TIME_GET_HOUR(t);
+
+                 PyDateTime_TIME_GET_MINUTE(obj);
+                 PyDateTime_TIME_GET_MINUTE(t);
+
+                 PyDateTime_TIME_GET_SECOND(obj);
+                 PyDateTime_TIME_GET_SECOND(t);
+
+                 PyDateTime_TIME_GET_MICROSECOND(obj);
+                 PyDateTime_TIME_GET_MICROSECOND(t);
+
+                 return obj;
+             """),
+            ("test_delta_macros", "METH_NOARGS",
+             """
+                 PyDateTime_IMPORT;
+                 if (!PyDateTimeAPI) {
+                     PyErr_SetString(PyExc_RuntimeError, "No PyDateTimeAPI");
+                     return NULL;
+                 }
+                 PyObject* obj = PyDelta_FromDSU(6, 6, 6);
+                 PyDateTime_Delta* delta = (PyDateTime_Delta*)obj;
+
+                 PyDateTime_DELTA_GET_DAYS(obj);
+                 PyDateTime_DELTA_GET_DAYS(delta);
+
+                 PyDateTime_DELTA_GET_SECONDS(obj);
+                 PyDateTime_DELTA_GET_SECONDS(delta);
+
+                 PyDateTime_DELTA_GET_MICROSECONDS(obj);
+                 PyDateTime_DELTA_GET_MICROSECONDS(delta);
+
+                 return obj;
+             """),
+            ])
diff --git a/pypy/module/cpyext/test/test_floatobject.py 
b/pypy/module/cpyext/test/test_floatobject.py
--- a/pypy/module/cpyext/test/test_floatobject.py
+++ b/pypy/module/cpyext/test/test_floatobject.py
@@ -77,3 +77,19 @@
         neginf = module.return_neginf()
         assert neginf < 0
         assert math.isinf(neginf)
+
+    def test_macro_accepts_wrong_pointer_type(self):
+        import math
+
+        module = self.import_extension('foo', [
+            ("test_macros", "METH_NOARGS",
+             """
+             PyObject* o = PyFloat_FromDouble(1.0);
+             // no PyFloatObject
+             char* dumb_pointer = (char*)o;
+
+             PyFloat_AS_DOUBLE(o);
+             PyFloat_AS_DOUBLE(dumb_pointer);
+
+             Py_RETURN_NONE;"""),
+            ])
diff --git a/pypy/module/cpyext/test/test_intobject.py 
b/pypy/module/cpyext/test/test_intobject.py
--- a/pypy/module/cpyext/test/test_intobject.py
+++ b/pypy/module/cpyext/test/test_intobject.py
@@ -191,3 +191,17 @@
         i = mod.test_int()
         assert isinstance(i, int)
         assert i == 42
+
+    def test_int_macros(self):
+        mod = self.import_extension('foo', [
+                ("test_macros", "METH_NOARGS",
+                """
+                PyObject * obj = PyInt_FromLong(42);
+                PyIntObject * i = (PyIntObject*)obj;
+                PyInt_AS_LONG(obj);
+                PyInt_AS_LONG(i);
+                Py_RETURN_NONE;
+                """
+                ),
+                ])
+
diff --git a/pypy/module/cpyext/test/test_listobject.py 
b/pypy/module/cpyext/test/test_listobject.py
--- a/pypy/module/cpyext/test/test_listobject.py
+++ b/pypy/module/cpyext/test/test_listobject.py
@@ -137,6 +137,33 @@
         module.setlistitem(l,0)
         assert l == [None, 2, 3]
 
+    def test_list_macros(self):
+        """The PyList_* macros cast, and calls expecting that build."""
+        module = self.import_extension('foo', [
+            ("test_macro_invocations", "METH_NOARGS",
+             """
+             PyObject* o = PyList_New(2);
+             PyListObject* l = (PyListObject*)o;
+
+
+             Py_INCREF(o);
+             PyList_SET_ITEM(o, 0, o);
+             Py_INCREF(o);
+             PyList_SET_ITEM(l, 1, o);
+
+             PyList_GET_ITEM(o, 0);
+             PyList_GET_ITEM(l, 1);
+
+             PyList_GET_SIZE(o);
+             PyList_GET_SIZE(l);
+
+             return o;
+             """
+            )
+        ])
+        x = module.test_macro_invocations()
+        assert x[0] is x[1] is x
+
     def test_get_item_macro(self):
         module = self.import_extension('foo', [
              ("test_get_item", "METH_NOARGS",
diff --git a/pypy/module/cpyext/test/test_sequence.py 
b/pypy/module/cpyext/test/test_sequence.py
--- a/pypy/module/cpyext/test/test_sequence.py
+++ b/pypy/module/cpyext/test/test_sequence.py
@@ -155,6 +155,28 @@
         result = api.PySequence_Index(w_gen, w_tofind)
         assert result == 4
 
+class AppTestSetObject(AppTestCpythonExtensionBase):
+    def test_sequence_macro_cast(self):
+        module = self.import_extension('foo', [
+            ("test_macro_cast", "METH_NOARGS",
+             """
+             PyObject* o = PyList_New(0);
+             PyList_Append(o, o);
+             PyListObject* l = (PyListObject*)o;
+
+             PySequence_Fast_GET_ITEM(o, 0);
+             PySequence_Fast_GET_ITEM(l, 0);
+
+             PySequence_Fast_GET_SIZE(o);
+             PySequence_Fast_GET_SIZE(l);
+
+             PySequence_ITEM(o, 0);
+             PySequence_ITEM(l, 0);
+
+             return o;
+             """
+            )
+        ])
 class TestCPyListStrategy(BaseApiTest):
     def test_getitem_setitem(self, space, api):
         w_l = space.wrap([1, 2, 3, 4])
diff --git a/pypy/module/cpyext/test/test_setobject.py 
b/pypy/module/cpyext/test/test_setobject.py
--- a/pypy/module/cpyext/test/test_setobject.py
+++ b/pypy/module/cpyext/test/test_setobject.py
@@ -2,6 +2,7 @@
 
 from pypy.module.cpyext.pyobject import PyObject, PyObjectP, make_ref, from_ref
 from pypy.module.cpyext.test.test_api import BaseApiTest
+from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
 from rpython.rtyper.lltypesystem import rffi, lltype
 
 
@@ -45,3 +46,20 @@
         w_frozenset = space.newfrozenset([space.wrap(i) for i in [1, 2, 3, 4]])
         assert api.PyAnySet_CheckExact(w_set)
         assert api.PyAnySet_CheckExact(w_frozenset)
+
+class AppTestSetObject(AppTestCpythonExtensionBase):
+    def test_set_macro_cast(self):
+        module = self.import_extension('foo', [
+            ("test_macro_cast", "METH_NOARGS",
+             """
+             PyObject* o = PySet_New(NULL);
+             // no PySetObject
+             char* dumb_pointer = (char*) o;
+
+             PySet_GET_SIZE(o);
+             PySet_GET_SIZE(dumb_pointer);
+
+             return o;
+             """
+            )
+        ])
diff --git a/pypy/module/cpyext/test/test_translate.py 
b/pypy/module/cpyext/test/test_translate.py
--- a/pypy/module/cpyext/test/test_translate.py
+++ b/pypy/module/cpyext/test/test_translate.py
@@ -11,11 +11,11 @@
     FT = lltype.FuncType([], lltype.Signed)
     FTPTR = lltype.Ptr(FT)
 
-    def make_wrapper(space, func, gil=None):
+    def make_wrapper(self, space):
         def wrapper():
-            return func(space)
+            return self.callable(space)
         return wrapper
-    monkeypatch.setattr(pypy.module.cpyext.api, 'make_wrapper', make_wrapper)
+    monkeypatch.setattr(pypy.module.cpyext.api.ApiFunction, '_make_wrapper', 
make_wrapper)
 
     @specialize.memo()
     def get_tp_function(space, typedef):
diff --git a/pypy/module/cpyext/test/test_unicodeobject.py 
b/pypy/module/cpyext/test/test_unicodeobject.py
--- a/pypy/module/cpyext/test/test_unicodeobject.py
+++ b/pypy/module/cpyext/test/test_unicodeobject.py
@@ -111,6 +111,26 @@
         assert isinstance(res, str)
         assert res == 'caf?'
 
+    def test_unicode_macros(self):
+        """The PyUnicode_* macros cast, and calls expecting that build."""
+        module = self.import_extension('foo', [
+             ("test_macro_invocations", "METH_NOARGS",
+             """
+                PyObject* o = PyUnicode_FromString("");
+                PyUnicodeObject* u = (PyUnicodeObject*)o;
+
+                PyUnicode_GET_SIZE(u);
+                PyUnicode_GET_SIZE(o);
+
+                PyUnicode_GET_DATA_SIZE(u);
+                PyUnicode_GET_DATA_SIZE(o);
+
+                PyUnicode_AS_UNICODE(o);
+                PyUnicode_AS_UNICODE(u);
+                return o;
+             """)])
+        assert module.test_macro_invocations() == u''
+
 class TestUnicode(BaseApiTest):
     def test_unicodeobject(self, space, api):
         assert api.PyUnicode_GET_SIZE(space.wrap(u'sp&#65533;m')) == 4
diff --git a/pypy/module/cpyext/test/test_weakref.py 
b/pypy/module/cpyext/test/test_weakref.py
--- a/pypy/module/cpyext/test/test_weakref.py
+++ b/pypy/module/cpyext/test/test_weakref.py
@@ -7,7 +7,6 @@
         w_ref = api.PyWeakref_NewRef(w_obj, space.w_None)
         assert w_ref is not None
         assert space.is_w(api.PyWeakref_GetObject(w_ref), w_obj)
-        assert space.is_w(api.PyWeakref_GET_OBJECT(w_ref), w_obj)
         assert space.is_w(api.PyWeakref_LockObject(w_ref), w_obj)
 
         w_obj = space.newtuple([])
@@ -34,3 +33,25 @@
         del w_obj
         import gc; gc.collect()
         assert space.is_w(api.PyWeakref_LockObject(w_ref), space.w_None)
+
+
+class AppTestWeakReference(AppTestCpythonExtensionBase):
+
+    def test_weakref_macro(self):
+        module = self.import_extension('foo', [
+            ("test_macro_cast", "METH_NOARGS",
+             """
+             // PyExc_Warning is some weak-reffable PyObject*.
+             PyObject* weakref_obj = PyWeakref_NewRef(PyExc_Warning, NULL);
+             if (!weakref_obj) return weakref_obj;
+             // No public PyWeakReference type.
+             char* dumb_pointer = (char*) weakref_obj;
+
+             PyWeakref_GET_OBJECT(weakref_obj);
+             PyWeakref_GET_OBJECT(dumb_pointer);
+
+             return weakref_obj;
+             """
+            )
+        ])
+        module.test_macro_cast()
diff --git a/pypy/module/cpyext/unicodeobject.py 
b/pypy/module/cpyext/unicodeobject.py
--- a/pypy/module/cpyext/unicodeobject.py
+++ b/pypy/module/cpyext/unicodeobject.py
@@ -188,33 +188,33 @@
     """Get the maximum ordinal for a Unicode character."""
     return runicode.UNICHR(runicode.MAXUNICODE)
 
-@cpython_api([PyObject], rffi.CCHARP, error=CANNOT_FAIL)
+@cpython_api([rffi.VOIDP], rffi.CCHARP, error=CANNOT_FAIL)
 def PyUnicode_AS_DATA(space, ref):
     """Return a pointer to the internal buffer of the object. o has to be a
     PyUnicodeObject (not checked)."""
     return rffi.cast(rffi.CCHARP, PyUnicode_AS_UNICODE(space, ref))
 
-@cpython_api([PyObject], Py_ssize_t, error=CANNOT_FAIL)
+@cpython_api([rffi.VOIDP], Py_ssize_t, error=CANNOT_FAIL)
 def PyUnicode_GET_DATA_SIZE(space, w_obj):
     """Return the size of the object's internal buffer in bytes.  o has to be a
     PyUnicodeObject (not checked)."""
     return rffi.sizeof(lltype.UniChar) * PyUnicode_GET_SIZE(space, w_obj)
 
-@cpython_api([PyObject], Py_ssize_t, error=CANNOT_FAIL)
+@cpython_api([rffi.VOIDP], Py_ssize_t, error=CANNOT_FAIL)
 def PyUnicode_GET_SIZE(space, w_obj):
     """Return the size of the object.  o has to be a PyUnicodeObject (not
     checked)."""
     assert isinstance(w_obj, unicodeobject.W_UnicodeObject)
     return space.len_w(w_obj)
 
-@cpython_api([PyObject], rffi.CWCHARP, error=CANNOT_FAIL)
+@cpython_api([rffi.VOIDP], rffi.CWCHARP, error=CANNOT_FAIL)
 def PyUnicode_AS_UNICODE(space, ref):
     """Return a pointer to the internal Py_UNICODE buffer of the object.  ref
     has to be a PyUnicodeObject (not checked)."""
     ref_unicode = rffi.cast(PyUnicodeObject, ref)
     if not ref_unicode.c_str:
         # Copy unicode buffer
-        w_unicode = from_ref(space, ref)
+        w_unicode = from_ref(space, rffi.cast(PyObject, ref))
         u = space.unicode_w(w_unicode)
         ref_unicode.c_str = rffi.unicode2wcharp(u)
     return ref_unicode.c_str
@@ -227,7 +227,7 @@
     w_type = from_ref(space, rffi.cast(PyObject, ref.c_ob_type))
     if not space.is_true(space.issubtype(w_type, space.w_unicode)):
         raise oefmt(space.w_TypeError, "expected unicode object")
-    return PyUnicode_AS_UNICODE(space, ref)
+    return PyUnicode_AS_UNICODE(space, rffi.cast(rffi.VOIDP, ref))
 
 @cpython_api([PyObject], Py_ssize_t, error=-1)
 def PyUnicode_GetSize(space, ref):
@@ -247,7 +247,7 @@
     string may or may not be 0-terminated.  It is the responsibility of the 
caller
     to make sure that the wchar_t string is 0-terminated in case this is
     required by the application."""
-    c_str = PyUnicode_AS_UNICODE(space, rffi.cast(PyObject, ref))
+    c_str = PyUnicode_AS_UNICODE(space, rffi.cast(rffi.VOIDP, ref))
     c_length = ref.c_length
 
     # If possible, try to copy the 0-termination as well
diff --git a/pypy/module/cpyext/weakrefobject.py 
b/pypy/module/cpyext/weakrefobject.py
--- a/pypy/module/cpyext/weakrefobject.py
+++ b/pypy/module/cpyext/weakrefobject.py
@@ -1,6 +1,7 @@
 from pypy.module.cpyext.api import cpython_api
 from pypy.module.cpyext.pyobject import PyObject
 from pypy.module._weakref.interp__weakref import W_Weakref, proxy
+from rpython.rtyper.lltypesystem import rffi
 
 @cpython_api([PyObject, PyObject], PyObject)
 def PyWeakref_NewRef(space, w_obj, w_callback):
@@ -37,7 +38,7 @@
     """
     return space.call_function(w_ref)     # borrowed ref
 
-@cpython_api([PyObject], PyObject, result_borrowed=True)
+@cpython_api([rffi.VOIDP], PyObject, result_borrowed=True)
 def PyWeakref_GET_OBJECT(space, w_ref):
     """Similar to PyWeakref_GetObject(), but implemented as a macro that does 
no
     error checking.
diff --git a/pypy/module/imp/importing.py b/pypy/module/imp/importing.py
--- a/pypy/module/imp/importing.py
+++ b/pypy/module/imp/importing.py
@@ -55,6 +55,14 @@
 
     return '.' + soabi + SO
 
+def log_pyverbose(space, level, message):
+    if space.sys.w_initialdict is None:
+        return # sys module not initialised, avoid recursion
+    verbose = space.sys.get_flag('verbose')
+    if verbose >= level:
+        w_stderr = space.sys.get('stderr')
+        space.call_method(w_stderr, "write", space.wrap(message))
+
 def file_exists(path):
     """Tests whether the given path is an existing regular file."""
     return os.path.isfile(path) and case_ok(path)
@@ -537,6 +545,7 @@
 
             path = space.str0_w(w_pathitem)
             filepart = os.path.join(path, partname)
+            log_pyverbose(space, 2, "# trying %s" % (filepart,))
             if os.path.isdir(filepart) and case_ok(filepart):
                 initfile = os.path.join(filepart, '__init__')
                 modtype, _, _ = find_modtype(space, initfile)
@@ -581,6 +590,8 @@
 
 def load_c_extension(space, filename, modulename):
     from pypy.module.cpyext.api import load_extension_module
+    log_pyverbose(space, 1, "import %s # from %s\n" %
+                  (modulename, filename))
     load_extension_module(space, filename, modulename)
     # NB. cpyext.api.load_extension_module() can also delegate to _cffi_backend
 
@@ -881,6 +892,9 @@
     """
     w = space.wrap
 
+    log_pyverbose(space, 1, "import %s # from %s\n" %
+                  (space.str_w(w_modulename), pathname))
+
     src_stat = os.fstat(fd)
     cpathname = pathname + 'c'
     mtime = int(src_stat[stat.ST_MTIME])
@@ -1003,6 +1017,9 @@
     Load a module from a compiled file, execute it, and return its
     module object.
     """
+    log_pyverbose(space, 1, "import %s # compiled from %s\n" %
+                  (space.str_w(w_modulename), cpathname))
+
     if magic != get_pyc_magic(space):
         raise oefmt(space.w_ImportError, "Bad magic number in %s", cpathname)
     #print "loading pyc file:", cpathname
diff --git a/pypy/module/imp/test/test_import.py 
b/pypy/module/imp/test/test_import.py
--- a/pypy/module/imp/test/test_import.py
+++ b/pypy/module/imp/test/test_import.py
@@ -98,6 +98,9 @@
         'a=5\nb=6\rc="""hello\r\nworld"""\r', mode='wb')
     p.join('mod.py').write(
         'a=15\nb=16\rc="""foo\r\nbar"""\r', mode='wb')
+    setuppkg("verbose1pkg", verbosemod='a = 1729')
+    setuppkg("verbose2pkg", verbosemod='a = 1729')
+    setuppkg("verbose0pkg", verbosemod='a = 1729')
     setuppkg("test_bytecode",
              a = '',
              b = '',
@@ -719,6 +722,68 @@
             else:
                 raise AssertionError("should have failed")
 
+    def test_verbose_flag_1(self):
+        output = []
+        class StdErr(object):
+            def write(self, line):
+                output.append(line)
+
+        import sys
+        old_flags = sys.flags
+
+        class Flags(object):
+            verbose = 1
+            def __getattr__(self, name):
+                return getattr(old_flags, name)
+
+        sys.flags = Flags()
+        sys.stderr = StdErr()
+        try:
+            import verbose1pkg.verbosemod
+        finally:
+            reload(sys)
+        assert 'import verbose1pkg # from ' in output[-2]
+        assert 'import verbose1pkg.verbosemod # from ' in output[-1]
+
+    def test_verbose_flag_2(self):
+        output = []
+        class StdErr(object):
+            def write(self, line):
+                output.append(line)
+
+        import sys
+        old_flags = sys.flags
+
+        class Flags(object):
+            verbose = 2
+            def __getattr__(self, name):
+                return getattr(old_flags, name)
+
+        sys.flags = Flags()
+        sys.stderr = StdErr()
+        try:
+            import verbose2pkg.verbosemod
+        finally:
+            reload(sys)
+        assert any('import verbose2pkg # from ' in line
+                   for line in output[:-2])
+        assert output[-2].startswith('# trying')
+        assert 'import verbose2pkg.verbosemod # from ' in output[-1]
+
+    def test_verbose_flag_0(self):
+        output = []
+        class StdErr(object):
+            def write(self, line):
+                output.append(line)
+
+        import sys
+        sys.stderr = StdErr()
+        try:
+            import verbose0pkg.verbosemod
+        finally:
+            reload(sys)
+        assert not output
+
 
 class TestAbi:
     def test_abi_tag(self):
diff --git a/pypy/module/micronumpy/ndarray.py 
b/pypy/module/micronumpy/ndarray.py
--- a/pypy/module/micronumpy/ndarray.py
+++ b/pypy/module/micronumpy/ndarray.py
@@ -443,7 +443,7 @@
                         'array does not have imaginary part to set')
         self.implementation.set_imag(space, self, w_value)
 
-    def reshape(self, space, w_shape, order):
+    def reshape(self, space, w_shape, order=NPY.ANYORDER):
         new_shape = get_shape_from_iterable(space, self.get_size(), w_shape)
         new_impl = self.implementation.reshape(self, new_shape, order)
         if new_impl is not None:
diff --git a/pypy/module/micronumpy/test/test_ufuncs.py 
b/pypy/module/micronumpy/test/test_ufuncs.py
--- a/pypy/module/micronumpy/test/test_ufuncs.py
+++ b/pypy/module/micronumpy/test/test_ufuncs.py
@@ -1480,7 +1480,21 @@
 
     def test_outer(self):
         import numpy as np
-        from numpy import absolute
+        c = np.multiply.outer([1, 2, 3], [4, 5, 6])
+        assert c.shape == (3, 3)
+        assert (c ==[[ 4,  5,  6],
+                     [ 8, 10, 12],
+                     [12, 15, 18]]).all()
+        A = np.array([[1, 2, 3], [4, 5, 6]])
+        B = np.array([[1, 2, 3, 4]])
+        c = np.multiply.outer(A, B)
+        assert c.shape == (2, 3, 1, 4)
+        assert (c == [[[[ 1,  2,  3,  4]],
+                       [[ 2,  4,  6,  8]],
+                       [[ 3,  6,  9, 12]]],
+                      [[[ 4,  8, 12, 16]],
+                       [[ 5, 10, 15, 20]],
+                       [[ 6, 12, 18, 24]]]]).all()
         exc = raises(ValueError, np.absolute.outer, [-1, -2])
         assert exc.value[0] == 'outer product only supported for binary 
functions'
 
diff --git a/pypy/module/micronumpy/ufuncs.py b/pypy/module/micronumpy/ufuncs.py
--- a/pypy/module/micronumpy/ufuncs.py
+++ b/pypy/module/micronumpy/ufuncs.py
@@ -363,12 +363,18 @@
                 out = space.call_method(obj, '__array_wrap__', out, 
space.w_None)
             return out
 
-    def descr_outer(self, space, __args__):
-        return self._outer(space, __args__)
-
-    def _outer(self, space, __args__):
-        raise oefmt(space.w_ValueError,
+    def descr_outer(self, space, args_w):
+        if self.nin != 2:
+            raise oefmt(space.w_ValueError,
                     "outer product only supported for binary functions")
+        if len(args_w) != 2:
+            raise oefmt(space.w_ValueError,
+                    "exactly two arguments expected")
+        args = [convert_to_array(space, w_obj) for w_obj in args_w]
+        w_outshape = [space.wrap(i) for i in args[0].get_shape() + 
[1]*args[1].ndims()]
+        args0 = args[0].reshape(space, space.newtuple(w_outshape))
+        return self.descr_call(space, Arguments.frompacked(space, 
+                                                        space.newlist([args0, 
args[1]])))
 
     def parse_kwargs(self, space, kwds_w):
         w_casting = kwds_w.pop('casting', None)
diff --git a/pypy/tool/test/test_tab.py b/pypy/tool/test/test_tab.py
--- a/pypy/tool/test/test_tab.py
+++ b/pypy/tool/test/test_tab.py
@@ -7,7 +7,11 @@
 
 ROOT = os.path.abspath(os.path.join(pypydir, '..'))
 RPYTHONDIR = os.path.join(ROOT, "rpython")
-EXCLUDE = {'/virt_test/lib/python2.7/site-packages/setuptools'}
+
+EXCLUDE = {'/virt_test'}
+# ^^^ don't look inside this: it is created by virtualenv on buildslaves.
+# It contains third-party installations that may include tabs in their
+# .py files.
 
 
 def test_no_tabs():
diff --git a/rpython/jit/backend/zarch/regalloc.py 
b/rpython/jit/backend/zarch/regalloc.py
--- a/rpython/jit/backend/zarch/regalloc.py
+++ b/rpython/jit/backend/zarch/regalloc.py
@@ -312,13 +312,21 @@
             even, odd = r.r2, r.r3
             old_even_var = reverse_mapping.get(even, None)
             old_odd_var = reverse_mapping.get(odd, None)
+
+            # forbid r2 and r3 to be in free regs!
+            self.free_regs = [fr for fr in self.free_regs \
+                              if fr is not even and \
+                                 fr is not odd]
+
             if old_even_var:
                 if old_even_var in forbidden_vars:
                     self._relocate_forbidden_variable(even, old_even_var, 
reverse_mapping,
                                                       forbidden_vars, odd)
                 else:
+                    # old even var is not forbidden, sync it and be done with 
it
                     self._sync_var(old_even_var)
                     del self.reg_bindings[old_even_var]
+                    del reverse_mapping[odd]
             if old_odd_var:
                 if old_odd_var in forbidden_vars:
                     self._relocate_forbidden_variable(odd, old_odd_var, 
reverse_mapping,
@@ -326,10 +334,8 @@
                 else:
                     self._sync_var(old_odd_var)
                     del self.reg_bindings[old_odd_var]
+                    del reverse_mapping[odd]
 
-            self.free_regs = [fr for fr in self.free_regs \
-                              if fr is not even and \
-                                 fr is not odd]
             self.reg_bindings[even_var] = even
             self.reg_bindings[odd_var] = odd
             return even, odd
@@ -342,10 +348,11 @@
             self.assembler.regalloc_mov(reg, candidate)
             self.reg_bindings[var] = candidate
             reverse_mapping[candidate] = var
+            return # we found a location for that forbidden var!
 
         for candidate in r.MANAGED_REGS:
             # move register of var to another register
-            # thus it is not allowed to bei either reg or forbidden_reg
+            # it is NOT allowed to be a reg or forbidden_reg
             if candidate is reg or candidate is forbidden_reg:
                 continue
             # neither can we allow to move it to a register of another 
forbidden variable
@@ -354,11 +361,11 @@
                 if candidate_var is not None:
                     self._sync_var(candidate_var)
                     del self.reg_bindings[candidate_var]
+                    del reverse_mapping[candidate]
                 self.assembler.regalloc_mov(reg, candidate)
                 assert var is not None
                 self.reg_bindings[var] = candidate
                 reverse_mapping[candidate] = var
-                self.free_regs.append(reg)
                 break
         else:
             raise NoVariableToSpill
diff --git a/rpython/memory/gc/env.py b/rpython/memory/gc/env.py
--- a/rpython/memory/gc/env.py
+++ b/rpython/memory/gc/env.py
@@ -210,7 +210,7 @@
             "Warning: cannot find your CPU L2 cache size in /proc/cpuinfo")
         return -1
 
-def get_L2cache_linux2_cpuinfo_s390x(filename="/proc/cpuinfo", label='cache3'):
+def get_L2cache_linux2_cpuinfo_s390x(filename="/proc/cpuinfo", label='cache2'):
     debug_start("gc-hardware")
     L2cache = sys.maxint
     try:
@@ -233,29 +233,19 @@
             start = _findend(data, '\n' + label, linepos)
             if start < 0:
                 break    # done
-            linepos = _findend(data, '\n', start)
-            if linepos < 0:
-                break    # no end-of-line??
-            # *** data[start:linepos] == "   : level=2 type=Instruction 
scope=Private size=2048K ..."
-            start = _skipspace(data, start)
-            if data[start] != ':':
+            start = _findend(data, 'size=', start)
+            if start < 0:
+                break
+            end = _findend(data, ' ', start) - 1
+            if end < 0:
+                break
+            linepos = end
+            size = data[start:end]
+            last_char = len(size)-1
+            assert 0 <= last_char < len(size)
+            if size[last_char] not in ('K', 'k'):    # assume kilobytes for now
                 continue
-            # *** data[start:linepos] == ": level=2 type=Instruction 
scope=Private size=2048K ..."
-            start = _skipspace(data, start + 1)
-            # *** data[start:linepos] == "level=2 type=Instruction 
scope=Private size=2048K ..."
-            start += 44
-            end = start
-            while '0' <= data[end] <= '9':
-                end += 1
-            # *** data[start:end] == "2048"
-            if start == end:
-                continue
-            number = int(data[start:end])
-            # *** data[end:linepos] == " KB\n"
-            end = _skipspace(data, end)
-            if data[end] not in ('K', 'k'):    # assume kilobytes for now
-                continue
-            number = number * 1024
+            number = int(size[:last_char])* 1024
             # for now we look for the smallest of the L2 caches of the CPUs
             if number < L2cache:
                 L2cache = number
diff --git a/rpython/memory/gc/test/test_env.py 
b/rpython/memory/gc/test/test_env.py
--- a/rpython/memory/gc/test/test_env.py
+++ b/rpython/memory/gc/test/test_env.py
@@ -162,21 +162,31 @@
     result = env.get_L2cache_linux2_cpuinfo(str(filepath))
     assert result == 3072 * 1024
 
-def test_estimate_best_nursery_size_linux2_s390x():
+def test_estimate_nursery_s390x():
     filepath = udir.join('estimate_best_nursery_size_linux2')
     filepath.write("""\
 vendor_id       : IBM/S390
 # processors    : 2
 bogomips per cpu: 20325.00
-features        : esan3 zarch stfle msa ldisp eimm dfp etf3eh highgprs 
-cache0          : level=1 type=Data scope=Private size=128K line_size=256 
associativity=8
-cache1          : level=1 type=Instruction scope=Private size=96K 
line_size=256 associativity=6
+...
 cache2          : level=2 type=Data scope=Private size=2048K line_size=256 
associativity=8
 cache3          : level=2 type=Instruction scope=Private size=2048K 
line_size=256 associativity=8
-cache4          : level=3 type=Unified scope=Shared size=65536K line_size=256 
associativity=16
-cache5          : level=4 type=Unified scope=Shared size=491520K line_size=256 
associativity=30
-processor 0: version = FF,  identification = 026A77,  machine = 2964
-processor 1: version = FF,  identification = 026A77,  machine = 2964
+...
 """)
     result = env.get_L2cache_linux2_cpuinfo_s390x(str(filepath))
     assert result == 2048 * 1024
+
+    filepath = udir.join('estimate_best_nursery_size_linux3')
+    filepath.write("""\
+vendor_id       : IBM/S390
+# processors    : 2
+bogomips per cpu: 9398.00
+...
+cache2          : level=2 type=Unified scope=Private size=1536K line_size=256 
associativity=12
+cache3          : level=3 type=Unified scope=Shared size=24576K line_size=256 
associativity=12
+...
+""")
+    result = env.get_L2cache_linux2_cpuinfo_s390x(str(filepath), 
label='cache3')
+    assert result == 24576 * 1024
+    result = env.get_L2cache_linux2_cpuinfo_s390x(str(filepath), 
label='cache2')
+    assert result == 1536 * 1024
diff --git a/rpython/tool/algo/test/test_regalloc.py 
b/rpython/tool/algo/test/test_regalloc.py
new file mode 100644
--- /dev/null
+++ b/rpython/tool/algo/test/test_regalloc.py
@@ -0,0 +1,60 @@
+from rpython.rtyper.test.test_llinterp import gengraph
+from rpython.rtyper.lltypesystem import lltype
+from rpython.tool.algo.regalloc import perform_register_allocation
+from rpython.flowspace.model import Variable
+from rpython.conftest import option
+
+
+def is_int(v):
+    return v.concretetype == lltype.Signed
+
+def check_valid(graph, regalloc, consider_var):
+    if getattr(option, 'view', False):
+        graph.show()
+    num_renamings = 0
+    for block in graph.iterblocks():
+        inputs = [v for v in block.inputargs if consider_var(v)]
+        colors = [regalloc.getcolor(v) for v in inputs]
+        print inputs, ':', colors
+        assert len(inputs) == len(set(colors))
+        in_use = dict(zip(colors, inputs))
+        for op in block.operations:
+            for v in op.args:
+                if isinstance(v, Variable) and consider_var(v):
+                    assert in_use[regalloc.getcolor(v)] is v
+            if consider_var(op.result):
+                in_use[regalloc.getcolor(op.result)] = op.result
+        for link in block.exits:
+            for i, v in enumerate(link.args):
+                if consider_var(v):
+                    assert in_use[regalloc.getcolor(v)] is v
+                    w = link.target.inputargs[i]
+                    if regalloc.getcolor(v) is not regalloc.getcolor(w):
+                        print '\trenaming %s:%d -> %s:%d' % (
+                            v, regalloc.getcolor(v), w, regalloc.getcolor(w))
+                        num_renamings += 1
+    return num_renamings
+
+
+def test_loop_1():
+    def f(a, b):
+        while a > 0:
+            b += a
+            a -= 1
+        return b
+    t, rtyper, graph = gengraph(f, [int, int], viewbefore=False)
+    regalloc = perform_register_allocation(graph, is_int)
+    num_renamings = check_valid(graph, regalloc, is_int)
+    assert num_renamings == 0
+
+def test_loop_2():
+    def f(a, b):
+        while a > 0:
+            b += a
+            if b < 10:
+                a, b = b, a
+            a -= 1
+        return b
+    t, rtyper, graph = gengraph(f, [int, int], viewbefore=False)
+    regalloc = perform_register_allocation(graph, is_int)
+    check_valid(graph, regalloc, is_int)
diff --git a/rpython/translator/c/src/int.h b/rpython/translator/c/src/int.h
--- a/rpython/translator/c/src/int.h
+++ b/rpython/translator/c/src/int.h
@@ -53,7 +53,21 @@
 /* addition, subtraction */
 
 #define OP_INT_ADD(x,y,r)     r = (x) + (y)
+#define OP_INT_SUB(x,y,r)     r = (x) - (y)
+#define OP_INT_MUL(x,y,r)     r = (x) * (y)
 
+
+#ifdef __GNUC__
+# if __GNUC__ >= 5
+#  define HAVE_BUILTIN_OVERFLOW
+# elif defined(__has_builtin)     /* clang */
+#  if __has_builtin(__builtin_mul_overflow)
+#   define HAVE_BUILTIN_OVERFLOW
+#  endif
+# endif
+#endif
+
+#ifndef HAVE_BUILTIN_OVERFLOW
 /* cast to avoid undefined behaviour on overflow */
 #define OP_INT_ADD_OVF(x,y,r) \
         r = (Signed)((Unsigned)x + y); \
@@ -63,14 +77,10 @@
         r = (Signed)((Unsigned)x + y); \
         if ((r&~x) < 0) FAIL_OVF("integer addition")
 
-#define OP_INT_SUB(x,y,r)     r = (x) - (y)
-
 #define OP_INT_SUB_OVF(x,y,r) \
         r = (Signed)((Unsigned)x - y); \
         if ((r^x) < 0 && (r^~y) < 0) FAIL_OVF("integer subtraction")
 
-#define OP_INT_MUL(x,y,r)     r = (x) * (y)
-
 #if SIZEOF_LONG * 2 <= SIZEOF_LONG_LONG && !defined(_WIN64)
 #define OP_INT_MUL_OVF(x,y,r) \
        { \
@@ -83,6 +93,17 @@
        r = op_llong_mul_ovf(x, y)   /* long == long long */
 #endif
 
+#else   /* HAVE_BUILTIN_OVERFLOW */
+#define OP_INT_ADD_NONNEG_OVF(x,y,r) OP_INT_ADD_OVF(x,y,r)
+#define OP_INT_ADD_OVF(x,y,r) \
+       if (__builtin_add_overflow(x, y, &r)) FAIL_OVF("integer addition")
+#define OP_INT_SUB_OVF(x,y,r) \
+       if (__builtin_sub_overflow(x, y, &r)) FAIL_OVF("integer subtraction")
+#define OP_INT_MUL_OVF(x,y,r) \
+       if (__builtin_mul_overflow(x, y, &r)) FAIL_OVF("integer multiplication")
+#endif
+
+
 /* shifting */
 
 /* NB. shifting has same limitations as C: the shift count must be
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to