Author: Matti Picus <matti.pi...@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 +@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. +@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 - +@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__', '') +@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)' +@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") +@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)' +@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()) +@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 +@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)' +@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)' +@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)) +@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)' +@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)' +@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) +@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 @@ # ____________________________________________________________ - +@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)) -@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) +@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 +@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' +@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' +@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' +@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' +@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' +@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' +@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' +@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' +@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, ¤t_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) { _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit