[pypy-commit] pypy buffer-interface2: merge default into branch

mattip pypy.commits at gmail.com
Fri Sep 30 08:40:58 EDT 2016


Author: Matti Picus <matti.picus at gmail.com>
Branch: buffer-interface2
Changeset: r87472:57f07a076df4
Date: 2016-09-30 13:16 +0300
http://bitbucket.org/pypy/pypy/changeset/57f07a076df4/

Log:	merge default into branch

diff --git a/Makefile b/Makefile
--- a/Makefile
+++ b/Makefile
@@ -40,4 +40,4 @@
 # http://lists.gnu.org/archive/html/help-make/2010-08/msg00106.html
 
 cffi_imports: pypy-c
-	PYTHONPATH=. ./pypy-c pypy/tool/build_cffi_imports.py
+	PYTHONPATH=. ./pypy-c pypy/tool/build_cffi_imports.py || /bin/true
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
@@ -32,3 +32,13 @@
 ``lib-python`` and ``lib_pypy``.  Of course, you can put a symlink to it
 from somewhere else.  You no longer have to do the same with the
 ``pypy`` executable, as long as it finds its ``libpypy-c.so`` library.
+
+.. branch: _warning
+
+CPython allows warning.warn(('something', 1), Warning), on PyPy this
+produced a "expected a readable buffer object" error. Test and fix.
+
+.. branch: stricter-strip
+
+CPython rejects 'a'.strip(buffer(' ')); only None, str or unicode are
+allowed as arguments. Test and fix for str and unicode
diff --git a/pypy/goal/targetpypystandalone.py b/pypy/goal/targetpypystandalone.py
--- a/pypy/goal/targetpypystandalone.py
+++ b/pypy/goal/targetpypystandalone.py
@@ -93,12 +93,10 @@
             home1 = rffi.charp2str(ll_home)
             home = os.path.join(home1, 'x') # <- so that 'll_home' can be
                                             # directly the root directory
-            dynamic = False
         else:
             home1 = "pypy's shared library location"
-            home = pypydir
-            dynamic = True
-        w_path = pypy_find_stdlib(space, home, dynamic)
+            home = '*'
+        w_path = pypy_find_stdlib(space, home)
         if space.is_none(w_path):
             if verbose:
                 debug("pypy_setup_home: directories 'lib-python' and 'lib_pypy'"
@@ -305,37 +303,20 @@
         # HACKHACKHACK
         # ugly hack to modify target goal from compile_* to build_cffi_imports
         # this should probably get cleaned up and merged with driver.create_exe
+        from rpython.tool.runsubprocess import run_subprocess
         from rpython.translator.driver import taskdef
         import types
 
-        class Options(object):
-            pass
-
-
-        def mkexename(name):
-            if sys.platform == 'win32':
-                name = name.new(ext='exe')
-            return name
-
         compile_goal, = driver.backend_select_goals(['compile'])
         @taskdef([compile_goal], "Create cffi bindings for modules")
         def task_build_cffi_imports(self):
-            from pypy.tool.build_cffi_imports import create_cffi_import_libraries
             ''' Use cffi to compile cffi interfaces to modules'''
-            exename = mkexename(driver.compute_exe_name())
-            basedir = exename
-            while not basedir.join('include').exists():
-                _basedir = basedir.dirpath()
-                if _basedir == basedir:
-                    raise ValueError('interpreter %s not inside pypy repo',
-                                     str(exename))
-                basedir = _basedir
-            modules = self.config.objspace.usemodules.getpaths()
-            options = Options()
-            # XXX possibly adapt options using modules
-            failures = create_cffi_import_libraries(exename, options, basedir)
-            # if failures, they were already printed
-            print  >> sys.stderr, str(exename),'successfully built (errors, if any, while building the above modules are ignored)'
+            filename = os.path.join(pypydir, 'tool', 'build_cffi_imports.py')
+            status, out, err = run_subprocess(str(driver.compute_exe_name()),
+                                              [filename])
+            sys.stdout.write(out)
+            sys.stderr.write(err)
+            # otherwise, ignore errors
         driver.task_build_cffi_imports = types.MethodType(task_build_cffi_imports, driver)
         driver.tasks['build_cffi_imports'] = driver.task_build_cffi_imports, [compile_goal]
         driver.default_goal = 'build_cffi_imports'
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -387,12 +387,12 @@
 class BufferInterfaceNotFound(Exception):
     pass
 
+ at specialize.memo()
 def wrappable_class_name(Class):
     try:
         return Class.typedef.name
     except AttributeError:
         return 'internal subclass of %s' % (Class.__name__,)
-wrappable_class_name._annspecialcase_ = 'specialize:memo'
 
 class CannotHaveLock(Exception):
     """Raised by space.allocate_lock() if we're translating."""
@@ -841,12 +841,13 @@
             assert type(s) is str
         return self.interned_strings.get(s) is not None
 
+    @specialize.arg(1)
     def descr_self_interp_w(self, RequiredClass, w_obj):
         if not isinstance(w_obj, RequiredClass):
             raise DescrMismatch()
         return w_obj
-    descr_self_interp_w._annspecialcase_ = 'specialize:arg(1)'
 
+    @specialize.arg(1)
     def interp_w(self, RequiredClass, w_obj, can_be_None=False):
         """
         Unwrap w_obj, checking that it is an instance of the required internal
@@ -861,7 +862,6 @@
                         wrappable_class_name(RequiredClass),
                         w_obj.getclass(self))
         return w_obj
-    interp_w._annspecialcase_ = 'specialize:arg(1)'
 
     def unpackiterable(self, w_iterable, expected_length=-1):
         """Unpack an iterable into a real (interpreter-level) list.
@@ -1300,6 +1300,7 @@
             self.setitem(w_globals, w_key, self.wrap(self.builtin))
         return statement.exec_code(self, w_globals, w_locals)
 
+    @specialize.arg(2)
     def appexec(self, posargs_w, source):
         """ return value from executing given source at applevel.
             EXPERIMENTAL. The source must look like
@@ -1311,7 +1312,6 @@
         w_func = self.fromcache(AppExecCache).getorbuild(source)
         args = Arguments(self, list(posargs_w))
         return self.call_args(w_func, args)
-    appexec._annspecialcase_ = 'specialize:arg(2)'
 
     def _next_or_none(self, w_it):
         try:
@@ -1321,6 +1321,7 @@
                 raise
             return None
 
+    @specialize.arg(3)
     def compare_by_iteration(self, w_iterable1, w_iterable2, op):
         w_it1 = self.iter(w_iterable1)
         w_it2 = self.iter(w_iterable2)
@@ -1343,7 +1344,6 @@
                 if op == 'gt': return self.gt(w_x1, w_x2)
                 if op == 'ge': return self.ge(w_x1, w_x2)
                 assert False, "bad value for op"
-    compare_by_iteration._annspecialcase_ = 'specialize:arg(3)'
 
     def decode_index(self, w_index_or_slice, seqlength):
         """Helper for custom sequence implementations
diff --git a/pypy/interpreter/executioncontext.py b/pypy/interpreter/executioncontext.py
--- a/pypy/interpreter/executioncontext.py
+++ b/pypy/interpreter/executioncontext.py
@@ -2,7 +2,7 @@
 from pypy.interpreter.error import OperationError, get_cleared_operation_error
 from rpython.rlib.unroll import unrolling_iterable
 from rpython.rlib.objectmodel import specialize
-from rpython.rlib import jit, rgc
+from rpython.rlib import jit, rgc, objectmodel
 
 TICK_COUNTER_STEP = 100
 
@@ -131,6 +131,7 @@
         if self.gettrace() is not None:
             self._trace(frame, 'return', w_retval)
 
+    @objectmodel.always_inline
     def bytecode_trace(self, frame, decr_by=TICK_COUNTER_STEP):
         "Trace function called before each bytecode."
         # this is split into a fast path and a slower path that is
@@ -139,7 +140,6 @@
         actionflag = self.space.actionflag
         if actionflag.decrement_ticker(decr_by) < 0:
             actionflag.action_dispatcher(self, frame)     # slow path
-    bytecode_trace._always_inline_ = True
 
     def _run_finalizers_now(self):
         # Tests only: run the actions now, to ensure that the
@@ -147,6 +147,7 @@
         # pypy.tool.pytest.apptest.
         self.space.actionflag.action_dispatcher(self, None)
 
+    @objectmodel.always_inline
     def bytecode_only_trace(self, frame):
         """
         Like bytecode_trace() but doesn't invoke any other events besides the
@@ -156,7 +157,6 @@
             self.gettrace() is None):
             return
         self.run_trace_func(frame)
-    bytecode_only_trace._always_inline_ = True
 
     @jit.unroll_safe
     def run_trace_func(self, frame):
@@ -203,13 +203,13 @@
 
         d.instr_prev_plus_one = frame.last_instr + 1
 
+    @objectmodel.try_inline
     def bytecode_trace_after_exception(self, frame):
         "Like bytecode_trace(), but without increasing the ticker."
         actionflag = self.space.actionflag
         self.bytecode_only_trace(frame)
         if actionflag.get_ticker() < 0:
             actionflag.action_dispatcher(self, frame)     # slow path
-    bytecode_trace_after_exception._always_inline_ = 'try'
     # NB. this function is not inlined right now.  backendopt.inline would
     # need some improvements to handle this case, but it's not really an
     # issue
@@ -456,6 +456,7 @@
         periodic_actions = unrolling_iterable(self._periodic_actions)
 
         @jit.unroll_safe
+        @objectmodel.dont_inline
         def action_dispatcher(ec, frame):
             # periodic actions (first reset the bytecode counter)
             self.reset_ticker(self.checkinterval_scaled)
@@ -477,7 +478,6 @@
                     action._fired = False
                     action.perform(ec, frame)
 
-        action_dispatcher._dont_inline_ = True
         self.action_dispatcher = action_dispatcher
 
 
diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py
--- a/pypy/interpreter/pyopcode.py
+++ b/pypy/interpreter/pyopcode.py
@@ -6,7 +6,8 @@
 
 from rpython.rlib import jit, rstackovf
 from rpython.rlib.debug import check_nonneg
-from rpython.rlib.objectmodel import we_are_translated
+from rpython.rlib.objectmodel import (we_are_translated, always_inline,
+        dont_inline)
 from rpython.rlib.rarithmetic import r_uint, intmask
 from rpython.tool.sourcetools import func_with_new_name
 
@@ -483,20 +484,20 @@
         # of oparg failed to produce an integer which is annotated as non-neg
         check_nonneg(oparg)
 
+    @always_inline
     def LOAD_FAST(self, varindex, next_instr):
         # access a local variable directly
         w_value = self.locals_cells_stack_w[varindex]
         if w_value is None:
             self._load_fast_failed(varindex)
         self.pushvalue(w_value)
-    LOAD_FAST._always_inline_ = True
 
+    @dont_inline
     def _load_fast_failed(self, varindex):
         varname = self.getlocalvarname(varindex)
         raise oefmt(self.space.w_UnboundLocalError,
                     "local variable '%s' referenced before assignment",
                     varname)
-    _load_fast_failed._dont_inline_ = True
 
     def LOAD_CONST(self, constindex, next_instr):
         w_const = self.getconstant_w(constindex)
@@ -888,6 +889,7 @@
                 return
         self.LOAD_GLOBAL(nameindex, next_instr)    # fall-back
 
+    @always_inline
     def _load_global(self, varname):
         w_value = self.space.finditem_str(self.get_w_globals(), varname)
         if w_value is None:
@@ -896,16 +898,15 @@
             if w_value is None:
                 self._load_global_failed(varname)
         return w_value
-    _load_global._always_inline_ = True
 
+    @dont_inline
     def _load_global_failed(self, varname):
         raise oefmt(self.space.w_NameError,
                     "global name '%s' is not defined", varname)
-    _load_global_failed._dont_inline_ = True
 
+    @always_inline
     def LOAD_GLOBAL(self, nameindex, next_instr):
         self.pushvalue(self._load_global(self.getname_u(nameindex)))
-    LOAD_GLOBAL._always_inline_ = True
 
     def DELETE_FAST(self, varindex, next_instr):
         if self.locals_cells_stack_w[varindex] is None:
@@ -939,6 +940,7 @@
         self.pushvalue(space.newlist([], sizehint=length_hint))
         self.pushvalue(last_val)
 
+    @always_inline
     def LOAD_ATTR(self, nameindex, next_instr):
         "obj.attributename"
         w_obj = self.popvalue()
@@ -949,7 +951,6 @@
             w_attributename = self.getname_w(nameindex)
             w_value = self.space.getattr(w_obj, w_attributename)
         self.pushvalue(w_value)
-    LOAD_ATTR._always_inline_ = True
 
     @jit.unroll_safe
     def cmp_exc_match(self, w_1, w_2):
diff --git a/pypy/interpreter/test/test_app_main.py b/pypy/interpreter/test/test_app_main.py
--- a/pypy/interpreter/test/test_app_main.py
+++ b/pypy/interpreter/test/test_app_main.py
@@ -1030,8 +1030,8 @@
             # If we are running PyPy with a libpypy-c, the following
             # lines find the stdlib anyway.  Otherwise, it is not found.
             expected_found = (
-                '__pypy__' in sys.builtin_module_names and
-                sys.pypy_translation_info['translation.shared'])
+                getattr(sys, 'pypy_translation_info', {})
+                .get('translation.shared'))
 
             import app_main
             app_main.setup_bootstrap_path(tmp_pypy_c)
diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py
--- a/pypy/interpreter/typedef.py
+++ b/pypy/interpreter/typedef.py
@@ -109,6 +109,7 @@
 # we need two subclasses of the app-level type, one to add mapdict, and then one
 # to add del to not slow down the GC.
 
+ at specialize.memo()
 def get_unique_interplevel_subclass(space, cls):
     "NOT_RPYTHON: initialization-time only"
     assert cls.typedef.acceptable_as_base_class
@@ -119,7 +120,6 @@
         assert cls not in _unique_subclass_cache
         _unique_subclass_cache[cls] = subcls
         return subcls
-get_unique_interplevel_subclass._annspecialcase_ = "specialize:memo"
 _unique_subclass_cache = {}
 
 def _getusercls(cls, reallywantdict=False):
diff --git a/pypy/module/_collections/interp_deque.py b/pypy/module/_collections/interp_deque.py
--- a/pypy/module/_collections/interp_deque.py
+++ b/pypy/module/_collections/interp_deque.py
@@ -6,6 +6,7 @@
 from pypy.interpreter.gateway import interp2app, unwrap_spec
 from pypy.interpreter.error import OperationError, oefmt
 from rpython.rlib.debug import check_nonneg
+from rpython.rlib.objectmodel import specialize
 
 
 # A `dequeobject` is composed of a doubly-linked list of `block` nodes.
@@ -316,12 +317,12 @@
             w_currently_in_repr = ec._py_repr = space.newdict()
         return dequerepr(space, w_currently_in_repr, space.wrap(self))
 
+    @specialize.arg(2)
     def compare(self, w_other, op):
         space = self.space
         if not isinstance(w_other, W_Deque):
             return space.w_NotImplemented
         return space.compare_by_iteration(space.wrap(self), w_other, op)
-    compare._annspecialcase_ = 'specialize:arg(2)'
 
     def lt(self, w_other):
         return self.compare(w_other, 'lt')
diff --git a/pypy/module/_csv/interp_reader.py b/pypy/module/_csv/interp_reader.py
--- a/pypy/module/_csv/interp_reader.py
+++ b/pypy/module/_csv/interp_reader.py
@@ -1,4 +1,5 @@
 from rpython.rlib.rstring import StringBuilder
+from rpython.rlib import objectmodel
 from pypy.interpreter.baseobjspace import W_Root
 from pypy.interpreter.error import OperationError, oefmt
 from pypy.interpreter.gateway import unwrap_spec
@@ -25,12 +26,12 @@
     def iter_w(self):
         return self.space.wrap(self)
 
+    @objectmodel.dont_inline
     def error(self, msg):
         space = self.space
         w_module = space.getbuiltinmodule('_csv')
         w_error = space.getattr(w_module, space.wrap('Error'))
         raise oefmt(w_error, "line %d: %s", self.line_num, msg)
-    error._dont_inline_ = True
 
     def add_char(self, field_builder, c):
         assert field_builder is not None
diff --git a/pypy/module/_csv/interp_writer.py b/pypy/module/_csv/interp_writer.py
--- a/pypy/module/_csv/interp_writer.py
+++ b/pypy/module/_csv/interp_writer.py
@@ -1,4 +1,5 @@
 from rpython.rlib.rstring import StringBuilder
+from rpython.rlib import objectmodel
 from pypy.interpreter.baseobjspace import W_Root
 from pypy.interpreter.error import OperationError
 from pypy.interpreter.typedef import TypeDef, interp2app
@@ -21,12 +22,12 @@
             special += dialect.quotechar
         self.special_characters = special
 
+    @objectmodel.dont_inline
     def error(self, msg):
         space = self.space
         w_module = space.getbuiltinmodule('_csv')
         w_error = space.getattr(w_module, space.wrap('Error'))
         raise OperationError(w_error, space.wrap(msg))
-    error._dont_inline_ = True
 
     def writerow(self, w_fields):
         """Construct and write a CSV record from a sequence of fields.
diff --git a/pypy/module/_lsprof/interp_lsprof.py b/pypy/module/_lsprof/interp_lsprof.py
--- a/pypy/module/_lsprof/interp_lsprof.py
+++ b/pypy/module/_lsprof/interp_lsprof.py
@@ -7,7 +7,7 @@
 from pypy.interpreter.typedef import (TypeDef, GetSetProperty,
                                       interp_attrproperty)
 from rpython.rlib import jit
-from rpython.rlib.objectmodel import we_are_translated
+from rpython.rlib.objectmodel import we_are_translated, always_inline
 from rpython.rlib.rtimer import read_timestamp, _is_64_bit
 from rpython.rtyper.lltypesystem import rffi, lltype
 from rpython.translator.tool.cbuild import ExternalCompilationInfo
@@ -256,7 +256,7 @@
         return w_frame.wrap_string(space)
     return w_frame    # actually a PyCode object
 
-
+ at always_inline
 def prepare_spec(space, w_arg):
     if isinstance(w_arg, Method):
         return (w_arg.w_function, w_arg.w_class)
@@ -264,8 +264,6 @@
         return (w_arg, None)
     else:
         return (None, space.type(w_arg))
-prepare_spec._always_inline_ = True
-
 
 def lsprof_call(space, w_self, frame, event, w_arg):
     assert isinstance(w_self, W_Profiler)
diff --git a/pypy/module/_pypyjson/interp_decoder.py b/pypy/module/_pypyjson/interp_decoder.py
--- a/pypy/module/_pypyjson/interp_decoder.py
+++ b/pypy/module/_pypyjson/interp_decoder.py
@@ -1,6 +1,6 @@
 import sys
 from rpython.rlib.rstring import StringBuilder
-from rpython.rlib.objectmodel import specialize
+from rpython.rlib.objectmodel import specialize, always_inline
 from rpython.rlib import rfloat, runicode
 from rpython.rtyper.lltypesystem import lltype, rffi
 from pypy.interpreter.error import oefmt
@@ -188,6 +188,7 @@
         self.pos = i
         return self.space.call_function(self.space.w_int, self.space.wrap(s))
 
+    @always_inline
     def parse_integer(self, i):
         "Parse a decimal number with an optional minus sign"
         sign = 1
@@ -218,7 +219,6 @@
         # overflowed
         ovf_maybe = (count >= OVF_DIGITS)
         return i, ovf_maybe, sign * intval
-    parse_integer._always_inline_ = True
 
     def decode_array(self, i):
         w_list = self.space.newlist([])
diff --git a/pypy/module/_pypyjson/targetjson.py b/pypy/module/_pypyjson/targetjson.py
--- a/pypy/module/_pypyjson/targetjson.py
+++ b/pypy/module/_pypyjson/targetjson.py
@@ -6,6 +6,7 @@
 import time
 from pypy.interpreter.error import OperationError
 from pypy.module._pypyjson.interp_decoder import loads
+from rpython.rlib.objectmodel import specialize, dont_inline
 
 
 ## MSG = open('msg.json').read()
@@ -68,11 +69,11 @@
         assert isinstance(w_x, W_String)
         return w_x.strval
 
+    @dont_inline
     def call_method(self, obj, name, arg):
         assert name == 'append'
         assert isinstance(obj, W_List)
         obj.listval.append(arg)
-    call_method._dont_inline_ = True
 
     def call_function(self, w_func, *args_w):
         return self.w_None # XXX
@@ -91,6 +92,7 @@
     def wrapfloat(self, x):
         return W_Float(x)
 
+    @specialize.argtype(1)
     def wrap(self, x):
         if isinstance(x, int):
             return W_Int(x)
@@ -100,7 +102,6 @@
         ##     assert False
         else:
             return W_Unicode(unicode(x))
-    wrap._annspecialcase_ = "specialize:argtype(1)"
 
 
 fakespace = FakeSpace()
diff --git a/pypy/module/_rawffi/interp_rawffi.py b/pypy/module/_rawffi/interp_rawffi.py
--- a/pypy/module/_rawffi/interp_rawffi.py
+++ b/pypy/module/_rawffi/interp_rawffi.py
@@ -9,6 +9,7 @@
 from rpython.rtyper.lltypesystem import lltype, rffi
 from rpython.rtyper.tool import rffi_platform
 from rpython.rlib.unroll import unrolling_iterable
+from rpython.rlib.objectmodel import specialize
 import rpython.rlib.rposix as rposix
 
 _MS_WINDOWS = os.name == "nt"
@@ -255,6 +256,7 @@
 
 _ARM = rffi_platform.getdefined('__arm__', '')
 
+ at specialize.arg(2)
 def read_ptr(ptr, ofs, TP):
     T = lltype.Ptr(rffi.CArray(TP))
     for c in unroll_letters_for_floats:
@@ -274,8 +276,8 @@
                 return ptr_val
     else:
         return rffi.cast(T, ptr)[ofs]
-read_ptr._annspecialcase_ = 'specialize:arg(2)'
 
+ at specialize.argtype(2)
 def write_ptr(ptr, ofs, value):
     TP = lltype.typeOf(value)
     T = lltype.Ptr(rffi.CArray(TP))
@@ -296,7 +298,6 @@
                 return
     else:
         rffi.cast(T, ptr)[ofs] = value
-write_ptr._annspecialcase_ = 'specialize:argtype(2)'
 
 def segfault_exception(space, reason):
     w_mod = space.getbuiltinmodule("_rawffi")
@@ -374,14 +375,15 @@
     def getrawsize(self):
         raise NotImplementedError("abstract base class")
 
+ at specialize.arg(0)
 def unwrap_truncate_int(TP, space, w_arg):
     if space.isinstance_w(w_arg, space.w_int):
         return rffi.cast(TP, space.int_w(w_arg))
     else:
         return rffi.cast(TP, space.bigint_w(w_arg).ulonglongmask())
-unwrap_truncate_int._annspecialcase_ = 'specialize:arg(0)'
 
 
+ at specialize.arg(1)
 def unwrap_value(space, push_func, add_arg, argdesc, letter, w_arg):
     if letter in TYPEMAP_PTR_LETTERS:
         # check for NULL ptr
@@ -422,10 +424,10 @@
                 return
         else:
             raise oefmt(space.w_TypeError, "cannot directly write value")
-unwrap_value._annspecialcase_ = 'specialize:arg(1)'
 
 ll_typemap_iter = unrolling_iterable(LL_TYPEMAP.items())
 
+ at specialize.arg(1)
 def wrap_value(space, func, add_arg, argdesc, letter):
     for c, ll_type in ll_typemap_iter:
         if letter == c:
@@ -437,7 +439,6 @@
             else:
                 return space.wrap(func(add_arg, argdesc, ll_type))
     raise oefmt(space.w_TypeError, "cannot directly read value")
-wrap_value._annspecialcase_ = 'specialize:arg(1)'
 
 NARROW_INTEGER_TYPES = 'cbhiBIH?'
 
diff --git a/pypy/module/_rawffi/structure.py b/pypy/module/_rawffi/structure.py
--- a/pypy/module/_rawffi/structure.py
+++ b/pypy/module/_rawffi/structure.py
@@ -18,6 +18,7 @@
 from rpython.rlib.rarithmetic import intmask, signedtype, r_uint, \
     r_ulonglong
 from rpython.rtyper.lltypesystem import lltype, rffi
+from rpython.rlib.objectmodel import specialize
 import sys
 
 IS_BIG_ENDIAN = sys.byteorder == 'big'
@@ -284,6 +285,7 @@
 def NUM_BITS(x):
     return x >> 16
 
+ at specialize.arg(1)
 def BIT_MASK(x, ll_t):
     if ll_t is lltype.SignedLongLong or ll_t is lltype.UnsignedLongLong:
         one = r_ulonglong(1)
@@ -291,8 +293,8 @@
         one = r_uint(1)
     # to avoid left shift by x == sizeof(ll_t)
     return (((one << (x - 1)) - 1) << 1) + 1
-BIT_MASK._annspecialcase_ = 'specialize:arg(1)'
 
+ at specialize.argtype(2)
 def push_field(self, num, value):
     ptr = rffi.ptradd(self.ll_buffer, self.shape.ll_positions[num])
     TP = lltype.typeOf(value)
@@ -313,8 +315,8 @@
                 value = rffi.cast(TP, current)
             break
     write_ptr(ptr, 0, value)
-push_field._annspecialcase_ = 'specialize:argtype(2)'
 
+ at specialize.arg(2)
 def cast_pos(self, i, ll_t):
     pos = rffi.ptradd(self.ll_buffer, self.shape.ll_positions[i])
     value = read_ptr(pos, 0, ll_t)
@@ -337,7 +339,6 @@
                 value = rffi.cast(ll_t, value)
             break
     return value
-cast_pos._annspecialcase_ = 'specialize:arg(2)'
 
 class W_StructureInstance(W_DataInstance):
     def __init__(self, space, shape, address):
diff --git a/pypy/module/_warnings/interp_warnings.py b/pypy/module/_warnings/interp_warnings.py
--- a/pypy/module/_warnings/interp_warnings.py
+++ b/pypy/module/_warnings/interp_warnings.py
@@ -248,6 +248,10 @@
     if space.isinstance_w(w_message, space.w_Warning):
         w_text = space.str(w_message)
         w_category = space.type(w_message)
+    elif (not space.isinstance_w(w_message, space.w_unicode) or
+          not space.isinstance_w(w_message, space.w_str)):
+        w_text = space.str(w_message)
+        w_message = space.call_function(w_category, w_message)
     else:
         w_text = w_message
         w_message = space.call_function(w_category, w_message)
diff --git a/pypy/module/_warnings/test/test_warnings.py b/pypy/module/_warnings/test/test_warnings.py
--- a/pypy/module/_warnings/test/test_warnings.py
+++ b/pypy/module/_warnings/test/test_warnings.py
@@ -11,6 +11,7 @@
         import _warnings
         _warnings.warn("some message", DeprecationWarning)
         _warnings.warn("some message", Warning)
+        _warnings.warn(("some message",1), Warning)
 
     def test_lineno(self):
         import warnings, _warnings, sys
@@ -40,7 +41,10 @@
     def test_show_source_line(self):
         import warnings
         import sys, StringIO
-        from test.warning_tests import inner
+        try:
+            from test.warning_tests import inner
+        except ImportError:
+            skip('no test, -A on cpython?')
         # With showarning() missing, make sure that output is okay.
         del warnings.showwarning
 
diff --git a/pypy/module/cpyext/slotdefs.py b/pypy/module/cpyext/slotdefs.py
--- a/pypy/module/cpyext/slotdefs.py
+++ b/pypy/module/cpyext/slotdefs.py
@@ -214,7 +214,9 @@
     i = space.int_w(space.index(args_w[0]))
     j = space.int_w(space.index(args_w[1]))
     w_y = args_w[2]
-    return space.wrap(generic_cpy_call(space, func_target, w_self, i, j, w_y))
+    res = generic_cpy_call(space, func_target, w_self, i, j, w_y)
+    if rffi.cast(lltype.Signed, res) == -1:
+        space.fromcache(State).check_and_raise_exception(always=True)
 
 def wrap_lenfunc(space, w_self, w_args, func):
     func_len = rffi.cast(lenfunc, func)
@@ -296,7 +298,10 @@
 def wrap_hashfunc(space, w_self, w_args, func):
     func_target = rffi.cast(hashfunc, func)
     check_num_args(space, w_args, 0)
-    return space.wrap(generic_cpy_call(space, func_target, w_self))
+    res = generic_cpy_call(space, func_target, w_self)
+    if res == -1:
+        space.fromcache(State).check_and_raise_exception(always=True)
+    return space.wrap(res)
 
 class CPyBuffer(Buffer):
     # Similar to Py_buffer
diff --git a/pypy/module/cpyext/test/test_arraymodule.py b/pypy/module/cpyext/test/test_arraymodule.py
--- a/pypy/module/cpyext/test/test_arraymodule.py
+++ b/pypy/module/cpyext/test/test_arraymodule.py
@@ -57,6 +57,7 @@
         assert arr.tolist() == [1, 21, 22, 23, 4]
         del arr[slice(1, 3)]
         assert arr.tolist() == [1, 23, 4]
+        raises(TypeError, 'arr[slice(1, 3)] = "abc"')
 
     def test_buffer(self):
         import sys
diff --git a/pypy/module/math/interp_math.py b/pypy/module/math/interp_math.py
--- a/pypy/module/math/interp_math.py
+++ b/pypy/module/math/interp_math.py
@@ -2,6 +2,7 @@
 import sys
 
 from rpython.rlib import rfloat
+from rpython.rlib.objectmodel import specialize
 from pypy.interpreter.error import OperationError, oefmt
 
 class State:
@@ -17,6 +18,7 @@
     else:
         return space.float_w(space.float(w_x))
 
+ at specialize.arg(1)
 def math1(space, f, w_x):
     x = _get_double(space, w_x)
     try:
@@ -26,8 +28,8 @@
     except ValueError:
         raise oefmt(space.w_ValueError, "math domain error")
     return space.wrap(y)
-math1._annspecialcase_ = 'specialize:arg(1)'
 
+ at specialize.arg(1)
 def math1_w(space, f, w_x):
     x = _get_double(space, w_x)
     try:
@@ -37,8 +39,8 @@
     except ValueError:
         raise oefmt(space.w_ValueError, "math domain error")
     return r
-math1_w._annspecialcase_ = 'specialize:arg(1)'
 
+ at specialize.arg(1)
 def math2(space, f, w_x, w_snd):
     x = _get_double(space, w_x)
     snd = _get_double(space, w_snd)
@@ -49,7 +51,6 @@
     except ValueError:
         raise oefmt(space.w_ValueError, "math domain error")
     return space.wrap(r)
-math2._annspecialcase_ = 'specialize:arg(1)'
 
 def trunc(space, w_x):
     """Truncate x."""
diff --git a/pypy/module/mmap/interp_mmap.py b/pypy/module/mmap/interp_mmap.py
--- a/pypy/module/mmap/interp_mmap.py
+++ b/pypy/module/mmap/interp_mmap.py
@@ -2,7 +2,7 @@
 from pypy.interpreter.baseobjspace import W_Root
 from pypy.interpreter.typedef import TypeDef
 from pypy.interpreter.gateway import interp2app, unwrap_spec
-from rpython.rlib import rmmap, rarithmetic
+from rpython.rlib import rmmap, rarithmetic, objectmodel
 from rpython.rlib.buffer import Buffer
 from rpython.rlib.rmmap import RValueError, RTypeError, RMMapError
 from rpython.rlib.rstring import StringBuilder
@@ -316,6 +316,7 @@
         self.w_error = space.new_exception_class("mmap.error",
                                                  space.w_EnvironmentError)
 
+ at objectmodel.dont_inline
 def mmap_error(space, e):
     if isinstance(e, RValueError):
         return OperationError(space.w_ValueError, space.wrap(e.message))
@@ -327,7 +328,6 @@
     else:
         # bogus 'e'?
         return OperationError(space.w_SystemError, space.wrap('%s' % e))
-mmap_error._dont_inline_ = True
 
 
 class MMapBuffer(Buffer):
diff --git a/pypy/module/pyexpat/interp_pyexpat.py b/pypy/module/pyexpat/interp_pyexpat.py
--- a/pypy/module/pyexpat/interp_pyexpat.py
+++ b/pypy/module/pyexpat/interp_pyexpat.py
@@ -7,6 +7,7 @@
 from rpython.rtyper.tool import rffi_platform
 from rpython.translator.tool.cbuild import ExternalCompilationInfo
 from rpython.translator.platform import platform
+from rpython.rlib.objectmodel import specialize
 
 import sys
 import weakref
@@ -571,6 +572,7 @@
             return self.w_character_data_handler or space.w_None
         return self.handlers[index]
 
+    @specialize.arg(2)
     def sethandler(self, space, name, w_handler, index, setter, handler):
         if name == 'CharacterDataHandler':
             self.flush_character_buffer(space)
@@ -582,8 +584,6 @@
         self.handlers[index] = w_handler
         setter(self.itself, handler)
 
-    sethandler._annspecialcase_ = 'specialize:arg(2)'
-
     all_chars = ''.join(chr(i) for i in range(256))
 
     def UnknownEncodingHandler(self, space, name, info):
diff --git a/pypy/module/select/interp_select.py b/pypy/module/select/interp_select.py
--- a/pypy/module/select/interp_select.py
+++ b/pypy/module/select/interp_select.py
@@ -2,6 +2,7 @@
 
 from rpython.rlib import _rsocket_rffi as _c, rpoll
 from rpython.rtyper.lltypesystem import lltype, rffi
+from rpython.rlib import objectmodel
 
 from pypy.interpreter.baseobjspace import W_Root
 from pypy.interpreter.error import OperationError, oefmt, wrap_oserror
@@ -91,7 +92,7 @@
 
 # ____________________________________________________________
 
-
+ at objectmodel.always_inline  # get rid of the tuple result
 def _build_fd_set(space, list_w, ll_list, nfds):
     _c.FD_ZERO(ll_list)
     fdlist = []
@@ -105,7 +106,6 @@
         _c.FD_SET(fd, ll_list)
         fdlist.append(fd)
     return fdlist, nfds
-_build_fd_set._always_inline_ = True    # get rid of the tuple result
 
 
 def _unbuild_fd_set(space, list_w, fdlist, ll_list, reslist_w):
diff --git a/pypy/module/sys/initpath.py b/pypy/module/sys/initpath.py
--- a/pypy/module/sys/initpath.py
+++ b/pypy/module/sys/initpath.py
@@ -7,7 +7,7 @@
 import stat
 import sys
 
-from rpython.rlib import rpath
+from rpython.rlib import rpath, rdynload
 from rpython.rlib.objectmodel import we_are_translated
 from rpython.rtyper.lltypesystem import lltype, rffi
 from rpython.translator.tool.cbuild import ExternalCompilationInfo
@@ -157,16 +157,20 @@
     return space.wrap(resolvedirof(filename))
 
 
- at unwrap_spec(executable='str0', dynamic=int)
-def pypy_find_stdlib(space, executable, dynamic=1):
-    if dynamic and space.config.translation.shared:
-        dynamic_location = pypy_init_home()
-        if dynamic_location:
-            executable = rffi.charp2str(dynamic_location)
-            pypy_init_free(dynamic_location)
-    path, prefix = find_stdlib(get_state(space), executable)
+ at unwrap_spec(executable='str0')
+def pypy_find_stdlib(space, executable):
+    path, prefix = None, None
+    if executable != '*':
+        path, prefix = find_stdlib(get_state(space), executable)
     if path is None:
-        return space.w_None
+        if space.config.translation.shared:
+            dynamic_location = pypy_init_home()
+            if dynamic_location:
+                dyn_path = rffi.charp2str(dynamic_location)
+                pypy_init_free(dynamic_location)
+                path, prefix = find_stdlib(get_state(space), dyn_path)
+        if path is None:
+            return space.w_None
     w_prefix = space.wrap(prefix)
     space.setitem(space.sys.w_dict, space.wrap('prefix'), w_prefix)
     space.setitem(space.sys.w_dict, space.wrap('exec_prefix'), w_prefix)
@@ -237,7 +241,9 @@
 }
 """
 
-_eci = ExternalCompilationInfo(separate_module_sources=[_source_code])
+_eci = ExternalCompilationInfo(separate_module_sources=[_source_code],
+    post_include_bits=['RPY_EXPORTED char *_pypy_init_home(void);'])
+_eci = _eci.merge(rdynload.eci)
 
 pypy_init_home = rffi.llexternal("_pypy_init_home", [], rffi.CCHARP,
                                  _nowrapper=True, compilation_info=_eci)
diff --git a/pypy/objspace/descroperation.py b/pypy/objspace/descroperation.py
--- a/pypy/objspace/descroperation.py
+++ b/pypy/objspace/descroperation.py
@@ -9,68 +9,68 @@
 from rpython.rlib.objectmodel import specialize
 from rpython.rlib import jit
 
+ at specialize.memo()
 def object_getattribute(space):
     "Utility that returns the app-level descriptor object.__getattribute__."
     w_src, w_getattribute = space.lookup_in_type_where(space.w_object,
                                                        '__getattribute__')
     return w_getattribute
-object_getattribute._annspecialcase_ = 'specialize:memo'
 
+ at specialize.memo()
 def object_setattr(space):
     "Utility that returns the app-level descriptor object.__setattr__."
     w_src, w_setattr = space.lookup_in_type_where(space.w_object,
                                                   '__setattr__')
     return w_setattr
-object_setattr._annspecialcase_ = 'specialize:memo'
 
+ at specialize.memo()
 def object_delattr(space):
     "Utility that returns the app-level descriptor object.__delattr__."
     w_src, w_delattr = space.lookup_in_type_where(space.w_object,
                                                   '__delattr__')
     return w_delattr
-object_delattr._annspecialcase_ = 'specialize:memo'
 
+ at specialize.memo()
 def object_hash(space):
     "Utility that returns the app-level descriptor object.__hash__."
     w_src, w_hash = space.lookup_in_type_where(space.w_object,
                                                   '__hash__')
     return w_hash
-object_hash._annspecialcase_ = 'specialize:memo'
 
+ at specialize.memo()
 def type_eq(space):
     "Utility that returns the app-level descriptor type.__eq__."
     w_src, w_eq = space.lookup_in_type_where(space.w_type,
                                              '__eq__')
     return w_eq
-type_eq._annspecialcase_ = 'specialize:memo'
 
+ at specialize.memo()
 def list_iter(space):
     "Utility that returns the app-level descriptor list.__iter__."
     w_src, w_iter = space.lookup_in_type_where(space.w_list,
                                                '__iter__')
     return w_iter
-list_iter._annspecialcase_ = 'specialize:memo'
 
+ at specialize.memo()
 def tuple_iter(space):
     "Utility that returns the app-level descriptor tuple.__iter__."
     w_src, w_iter = space.lookup_in_type_where(space.w_tuple,
                                                '__iter__')
     return w_iter
-tuple_iter._annspecialcase_ = 'specialize:memo'
 
+ at specialize.memo()
 def str_getitem(space):
     "Utility that returns the app-level descriptor str.__getitem__."
     w_src, w_iter = space.lookup_in_type_where(space.w_str,
                                                '__getitem__')
     return w_iter
-str_getitem._annspecialcase_ = 'specialize:memo'
 
+ at specialize.memo()
 def unicode_getitem(space):
     "Utility that returns the app-level descriptor unicode.__getitem__."
     w_src, w_iter = space.lookup_in_type_where(space.w_unicode,
                                                '__getitem__')
     return w_iter
-unicode_getitem._annspecialcase_ = 'specialize:memo'
 
 def raiseattrerror(space, w_obj, name, w_descr=None):
     if w_descr is None:
diff --git a/pypy/objspace/std/bytearrayobject.py b/pypy/objspace/std/bytearrayobject.py
--- a/pypy/objspace/std/bytearrayobject.py
+++ b/pypy/objspace/std/bytearrayobject.py
@@ -82,7 +82,8 @@
         return False
 
     @staticmethod
-    def _op_val(space, w_other):
+    def _op_val(space, w_other, strict=None):
+        # bytearray does not enforce the strict restriction (on strip at least)
         return space.buffer_w(w_other, space.BUF_SIMPLE).as_str()
 
     def _chr(self, char):
diff --git a/pypy/objspace/std/bytesobject.py b/pypy/objspace/std/bytesobject.py
--- a/pypy/objspace/std/bytesobject.py
+++ b/pypy/objspace/std/bytesobject.py
@@ -501,7 +501,10 @@
                 isinstance(w_other, W_UnicodeObject))
 
     @staticmethod
-    def _op_val(space, w_other):
+    def _op_val(space, w_other, strict=None):
+        if strict and not space.isinstance_w(w_other, space.w_str):
+            raise oefmt(space.w_TypeError,
+                "%s arg must be None, str or unicode", strict)
         try:
             return space.str_w(w_other)
         except OperationError as e:
diff --git a/pypy/objspace/std/formatting.py b/pypy/objspace/std/formatting.py
--- a/pypy/objspace/std/formatting.py
+++ b/pypy/objspace/std/formatting.py
@@ -7,6 +7,7 @@
 from rpython.rlib.rstring import StringBuilder, UnicodeBuilder
 from rpython.rlib.unroll import unrolling_iterable
 from rpython.tool.sourcetools import func_with_new_name
+from rpython.rlib.objectmodel import specialize
 
 from pypy.interpreter.error import OperationError, oefmt
 
@@ -344,6 +345,7 @@
                         "unsupported format character '%s' (%s) at index %d",
                         s, hex(ord(c)), self.fmtpos - 1)
 
+        @specialize.argtype(1)
         def std_wp(self, r):
             length = len(r)
             if do_unicode and isinstance(r, str):
@@ -369,7 +371,6 @@
             if padding > 0:
                 result.append_multiple_char(const(' '), padding)
             # add any remaining padding at the right
-        std_wp._annspecialcase_ = 'specialize:argtype(1)'
 
         def std_wp_number(self, r, prefix=''):
             result = self.result
diff --git a/pypy/objspace/std/objspace.py b/pypy/objspace/std/objspace.py
--- a/pypy/objspace/std/objspace.py
+++ b/pypy/objspace/std/objspace.py
@@ -351,6 +351,7 @@
         assert isinstance(w_starttype, W_TypeObject)
         return w_type.lookup_starting_at(w_starttype, name)
 
+    @specialize.arg(1)
     def allocate_instance(self, cls, w_subtype):
         """Allocate the memory needed for an instance of an internal or
         user-defined type, without actually __init__ializing the instance."""
@@ -375,7 +376,6 @@
                         "%N.__new__(%N): only for the type %N",
                         w_type, w_subtype, w_type)
         return instance
-    allocate_instance._annspecialcase_ = "specialize:arg(1)"
 
     # two following functions are almost identical, but in fact they
     # have different return type. First one is a resizable list, second
diff --git a/pypy/objspace/std/stringmethods.py b/pypy/objspace/std/stringmethods.py
--- a/pypy/objspace/std/stringmethods.py
+++ b/pypy/objspace/std/stringmethods.py
@@ -652,7 +652,7 @@
     def _strip(self, space, w_chars, left, right):
         "internal function called by str_xstrip methods"
         value = self._val(space)
-        chars = self._op_val(space, w_chars)
+        chars = self._op_val(space, w_chars, strict='strip')
 
         lpos = 0
         rpos = len(value)
diff --git a/pypy/objspace/std/test/test_bytearrayobject.py b/pypy/objspace/std/test/test_bytearrayobject.py
--- a/pypy/objspace/std/test/test_bytearrayobject.py
+++ b/pypy/objspace/std/test/test_bytearrayobject.py
@@ -128,7 +128,8 @@
 
         b = bytearray('mississippi')
 
-        for strip_type in str, memoryview:
+        for strip_type in str, memoryview, buffer:
+            print 'strip_type', strip_type
             assert b.strip(strip_type('i')) == 'mississipp'
             assert b.strip(strip_type('m')) == 'ississippi'
             assert b.strip(strip_type('pi')) == 'mississ'
diff --git a/pypy/objspace/std/test/test_bytesobject.py b/pypy/objspace/std/test/test_bytesobject.py
--- a/pypy/objspace/std/test/test_bytesobject.py
+++ b/pypy/objspace/std/test/test_bytesobject.py
@@ -251,6 +251,12 @@
         assert b'xyzzyhelloxyzzy'.strip(b'xyz') == b'hello'
         assert b'xyzzyhelloxyzzy'.lstrip(b'xyz') == b'helloxyzzy'
         assert b'xyzzyhelloxyzzy'.rstrip(b'xyz') == b'xyzzyhello'
+        exc = raises(TypeError, s.strip, buffer(' '))
+        assert str(exc.value) == 'strip arg must be None, str or unicode'
+        exc = raises(TypeError, s.rstrip, buffer(' '))
+        assert str(exc.value) == 'strip arg must be None, str or unicode'
+        exc = raises(TypeError, s.lstrip, buffer(' '))
+        assert str(exc.value) == 'strip arg must be None, str or unicode'
 
     def test_zfill(self):
         assert b'123'.zfill(2) == b'123'
@@ -656,7 +662,7 @@
         table = maketrans(b'abc', b'xyz')
         assert b'xyzxyz' == b'xyzabcdef'.translate(table, b'def')
         exc = raises(TypeError, "'xyzabcdef'.translate(memoryview(table), 'def')")
-        assert str(exc.value) == 'expected a character buffer object'
+        assert 'expected a' in str(exc.value)
 
         table = maketrans(b'a', b'A')
         assert b'Abc' == b'abc'.translate(table)
diff --git a/pypy/objspace/std/test/test_unicodeobject.py b/pypy/objspace/std/test/test_unicodeobject.py
--- a/pypy/objspace/std/test/test_unicodeobject.py
+++ b/pypy/objspace/std/test/test_unicodeobject.py
@@ -332,6 +332,12 @@
         assert u'xyzzyhelloxyzzy'.strip(u'xyz') == u'hello'
         assert u'xyzzyhelloxyzzy'.lstrip('xyz') == u'helloxyzzy'
         assert u'xyzzyhelloxyzzy'.rstrip(u'xyz') == u'xyzzyhello'
+        exc = raises(TypeError, s.strip, buffer(' '))
+        assert str(exc.value) == 'strip arg must be None, unicode or str'
+        exc = raises(TypeError, s.rstrip, buffer(' '))
+        assert str(exc.value) == 'strip arg must be None, unicode or str'
+        exc = raises(TypeError, s.lstrip, buffer(' '))
+        assert str(exc.value) == 'strip arg must be None, unicode or str'
 
     def test_strip_str_unicode(self):
         x = "--abc--".strip(u"-")
diff --git a/pypy/objspace/std/unicodeobject.py b/pypy/objspace/std/unicodeobject.py
--- a/pypy/objspace/std/unicodeobject.py
+++ b/pypy/objspace/std/unicodeobject.py
@@ -124,11 +124,14 @@
         return True
 
     @staticmethod
-    def _op_val(space, w_other):
+    def _op_val(space, w_other, strict=None):
         if isinstance(w_other, W_UnicodeObject):
             return w_other._value
         if space.isinstance_w(w_other, space.w_str):
             return unicode_from_string(space, w_other)._value
+        if strict:
+            raise oefmt(space.w_TypeError,
+                "%s arg must be None, unicode or str", strict)
         return unicode_from_encoded_object(
             space, w_other, None, "strict")._value
 
diff --git a/pypy/tool/build_cffi_imports.py b/pypy/tool/build_cffi_imports.py
--- a/pypy/tool/build_cffi_imports.py
+++ b/pypy/tool/build_cffi_imports.py
@@ -44,8 +44,8 @@
 if __name__ == '__main__':
     import py, os
     if '__pypy__' not in sys.builtin_module_names:
-        print 'Call with a pypy interpreter'
-        sys.exit(-1)
+        print >> sys.stderr, 'Call with a pypy interpreter'
+        sys.exit(1)
 
     class Options(object):
         pass
@@ -59,18 +59,26 @@
                                  str(exename))
         basedir = _basedir
     options = Options()
-    print >> sys.stderr, "There should be no failures here"
     failures = create_cffi_import_libraries(exename, options, basedir)
     if len(failures) > 0:
-        print '*** failed to build', [f[1] for f in failures]
+        print >> sys.stderr, '*** failed to build the CFFI modules %r' % (
+            [f[1] for f in failures],)
+        print >> sys.stderr, '''
+PyPy can still be used as long as you don't need the corresponding
+modules.  If you do need them, please install the missing headers and
+libraries (see error messages just above) and then re-run the command:
+
+    %s %s
+''' % (sys.executable, ' '.join(sys.argv))
         sys.exit(1)
 
-    # monkey patch a failure, just to test
-    print >> sys.stderr, 'This line should be followed by a traceback'
-    for k in cffi_build_scripts:
-        setattr(options, 'no_' + k, True)
-    must_fail = '_missing_build_script.py'
-    assert not os.path.exists(str(basedir.join('lib_pypy').join(must_fail)))
-    cffi_build_scripts['should_fail'] = must_fail
-    failures = create_cffi_import_libraries(exename, options, basedir)
-    assert len(failures) == 1
+    if len(sys.argv) > 1 and sys.argv[1] == '--test':
+        # monkey patch a failure, just to test
+        print >> sys.stderr, 'This line should be followed by a traceback'
+        for k in cffi_build_scripts:
+            setattr(options, 'no_' + k, True)
+        must_fail = '_missing_build_script.py'
+        assert not os.path.exists(str(basedir.join('lib_pypy').join(must_fail)))
+        cffi_build_scripts['should_fail'] = must_fail
+        failures = create_cffi_import_libraries(exename, options, basedir)
+        assert len(failures) == 1
diff --git a/rpython/jit/backend/x86/callbuilder.py b/rpython/jit/backend/x86/callbuilder.py
--- a/rpython/jit/backend/x86/callbuilder.py
+++ b/rpython/jit/backend/x86/callbuilder.py
@@ -138,6 +138,7 @@
             # shadowstack: change 'rpy_fastgil' to 0 (it should be
             # non-zero right now).
             self.change_extra_stack_depth = False
+            # ^^ note that set_extra_stack_depth() in this case is a no-op
             css_value = imm(0)
         else:
             from rpython.memory.gctransform import asmgcroot
diff --git a/rpython/rlib/objectmodel.py b/rpython/rlib/objectmodel.py
--- a/rpython/rlib/objectmodel.py
+++ b/rpython/rlib/objectmodel.py
@@ -217,6 +217,12 @@
     func._dont_inline_ = True
     return func
 
+def try_inline(func):
+    """ tell the RPython inline (not the JIT!), to try to inline this function,
+    no matter its size."""
+    func._always_inline_ = 'try'
+    return func
+
 
 # ____________________________________________________________
 
diff --git a/rpython/rlib/rdynload.py b/rpython/rlib/rdynload.py
--- a/rpython/rlib/rdynload.py
+++ b/rpython/rlib/rdynload.py
@@ -34,6 +34,7 @@
 else:
     libraries = ['dl']
 
+# this 'eci' is also used in pypy/module/sys/initpath.py
 eci = ExternalCompilationInfo(
     pre_include_bits = pre_include_bits,
     includes = includes,
diff --git a/rpython/rlib/rvmprof/src/vmprof_get_custom_offset.h b/rpython/rlib/rvmprof/src/vmprof_get_custom_offset.h
--- a/rpython/rlib/rvmprof/src/vmprof_get_custom_offset.h
+++ b/rpython/rlib/rvmprof/src/vmprof_get_custom_offset.h
@@ -4,17 +4,18 @@
                                 long *current_pos_addr);
 
 
+#define MAX_INLINE_DEPTH  384
+
+
 static long vmprof_write_header_for_jit_addr(intptr_t *result, long n,
-                                             intptr_t ip, int max_depth)
+                                             intptr_t addr, int max_depth)
 {
 #ifdef PYPY_JIT_CODEMAP
     void *codemap;
     long current_pos = 0;
-    intptr_t ident;
+    intptr_t ident, local_stack[MAX_INLINE_DEPTH];
+    long m;
     long start_addr = 0;
-    intptr_t addr = (intptr_t)ip;
-    int start, k;
-    intptr_t tmp;
 
     codemap = pypy_find_codemap_at_addr(addr, &start_addr);
     if (codemap == NULL || n >= max_depth - 2)
@@ -25,24 +26,29 @@
     // in the middle
     result[n++] = VMPROF_ASSEMBLER_TAG;
     result[n++] = start_addr;
-    start = n;
-    while (n < max_depth) {
+
+    // build the list of code idents corresponding to the current
+    // position inside this particular piece of assembler.  If (very
+    // unlikely) we get more than MAX_INLINE_DEPTH recursion levels
+    // all inlined inside this single piece of assembler, then stop:
+    // there will be some missing frames then.  Otherwise, we need to
+    // first collect 'local_stack' and then write it to 'result' in the
+    // opposite order, stopping at 'max_depth'.  Previous versions of
+    // the code would write the oldest calls and then stop---whereas
+    // what we really need it to write the newest calls and then stop.
+    m = 0;
+    while (m < MAX_INLINE_DEPTH) {
         ident = pypy_yield_codemap_at_addr(codemap, addr, &current_pos);
         if (ident == -1)
             // finish
             break;
         if (ident == 0)
             continue; // not main codemap
+        local_stack[m++] = ident;
+    }
+    while (m > 0 && n < max_depth) {
         result[n++] = VMPROF_JITTED_TAG;
-        result[n++] = ident;
-    }
-    k = 1;
-
-    while (k < (n - start) / 2) {
-        tmp = result[start + k];
-        result[start + k] = result[n - k];
-        result[n - k] = tmp;
-        k += 2;
+        result[n++] = local_stack[--m];
     }
 #endif
     return n;
diff --git a/rpython/rlib/test/test_objectmodel.py b/rpython/rlib/test/test_objectmodel.py
--- a/rpython/rlib/test/test_objectmodel.py
+++ b/rpython/rlib/test/test_objectmodel.py
@@ -7,7 +7,7 @@
     resizelist_hint, is_annotation_constant, always_inline, NOT_CONSTANT,
     iterkeys_with_hash, iteritems_with_hash, contains_with_hash,
     setitem_with_hash, getitem_with_hash, delitem_with_hash, import_from_mixin,
-    fetch_translated_config)
+    fetch_translated_config, try_inline)
 from rpython.translator.translator import TranslationContext, graphof
 from rpython.rtyper.test.tool import BaseRtypingTest
 from rpython.rtyper.test.test_llinterp import interpret
@@ -483,6 +483,13 @@
         return a, b, c
     assert f._always_inline_ is True
 
+def test_try_inline():
+    @try_inline
+    def f(a, b, c):
+        return a, b, c
+    assert f._always_inline_ == "try"
+
+
 def test_enforceargs_defaults():
     @enforceargs(int, int)
     def f(a, b=40):
diff --git a/rpython/translator/c/src/threadlocal.c b/rpython/translator/c/src/threadlocal.c
--- a/rpython/translator/c/src/threadlocal.c
+++ b/rpython/translator/c/src/threadlocal.c
@@ -15,9 +15,10 @@
 static int check_valid(void);
 
 void _RPython_ThreadLocals_Acquire(void) {
-    while (!pypy_lock_test_and_set(&pypy_threadlocal_lock, 1)) {
-        /* busy loop */
-    }
+    long old_value;
+    do {
+        old_value = pypy_lock_test_and_set(&pypy_threadlocal_lock, 1);
+    } while (old_value != 0);   /* busy loop */
     assert(check_valid());
 }
 void _RPython_ThreadLocals_Release(void) {


More information about the pypy-commit mailing list