Author: Armin Rigo <ar...@tunes.org> Branch: ppc-updated-backend Changeset: r79591:c9c35ead1602 Date: 2015-09-11 15:16 +0200 http://bitbucket.org/pypy/pypy/changeset/c9c35ead1602/
Log: hg merge decda77d1ea6 (branch optimize-cond-call) diff too long, truncating to 2000 out of 3637 lines diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -15,3 +15,4 @@ e03971291f3a0729ecd3ee7fae7ddb0bb82d476c release-2.6.0 e03971291f3a0729ecd3ee7fae7ddb0bb82d476c release-2.6.0 295ee98b69288471b0fcf2e0ede82ce5209eb90b release-2.6.0 +f3ad1e1e1d6215e20d34bb65ab85ff9188c9f559 release-2.6.1 diff --git a/LICENSE b/LICENSE --- a/LICENSE +++ b/LICENSE @@ -168,7 +168,6 @@ Michael Twomey Lucian Branescu Mihaila Yichao Yu - Anton Gulenko Gabriel Lavoie Olivier Dormond Jared Grubb @@ -215,6 +214,7 @@ Carl Meyer Karl Ramm Pieter Zieschang + Anton Gulenko Gabriel Lukas Vacek Andrew Dalke @@ -247,6 +247,7 @@ Toni Mattis Lucas Stadler Julian Berman + Markus Holtermann roberto@goyle Yury V. Zaytsev Anna Katrina Dominguez @@ -352,8 +353,7 @@ Except when otherwise stated (look for LICENSE files or copyright/license information at the beginning of each file) the files in the 'lib-python/2.7' directory are all copyrighted by the Python Software Foundation and licensed -under the Python Software License of which you can find a copy here: -http://www.python.org/doc/Copyright.html +under the terms that you can find here: https://docs.python.org/2/license.html License for 'pypy/module/unicodedata/' ====================================== @@ -430,9 +430,9 @@ gdbm module, provided in the file lib_pypy/gdbm.py, is redistributed under the terms of the GPL license as well. -License for 'pypy/module/_vmprof/src' +License for 'rpython/rlib/rvmprof/src' -------------------------------------- The code is based on gperftools. You may see a copy of the License for it at - https://code.google.com/p/gperftools/source/browse/COPYING + https://github.com/gperftools/gperftools/blob/master/COPYING diff --git a/lib_pypy/cffi.egg-info/PKG-INFO b/lib_pypy/cffi.egg-info/PKG-INFO --- a/lib_pypy/cffi.egg-info/PKG-INFO +++ b/lib_pypy/cffi.egg-info/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: cffi -Version: 1.2.0 +Version: 1.3.0 Summary: Foreign Function Interface for Python calling C code. Home-page: http://cffi.readthedocs.org Author: Armin Rigo, Maciej Fijalkowski diff --git a/lib_pypy/cffi/__init__.py b/lib_pypy/cffi/__init__.py --- a/lib_pypy/cffi/__init__.py +++ b/lib_pypy/cffi/__init__.py @@ -4,8 +4,8 @@ from .api import FFI, CDefError, FFIError from .ffiplatform import VerificationError, VerificationMissing -__version__ = "1.2.0" -__version_info__ = (1, 2, 0) +__version__ = "1.3.0" +__version_info__ = (1, 3, 0) # The verifier module file names are based on the CRC32 of a string that # contains the following version number. It may be older than __version__ diff --git a/lib_pypy/cffi/_cffi_include.h b/lib_pypy/cffi/_cffi_include.h --- a/lib_pypy/cffi/_cffi_include.h +++ b/lib_pypy/cffi/_cffi_include.h @@ -46,7 +46,7 @@ # endif #else # include <stdint.h> -# if (defined (__SVR4) && defined (__sun)) || defined(_AIX) +# if (defined (__SVR4) && defined (__sun)) || defined(_AIX) || defined(__hpux) # include <alloca.h> # endif #endif @@ -214,6 +214,12 @@ (size) == 8 ? ((sign) ? _CFFI_PRIM_INT64 : _CFFI_PRIM_UINT64) : \ _CFFI__UNKNOWN_PRIM) +#define _cffi_prim_float(size) \ + ((size) == sizeof(float) ? _CFFI_PRIM_FLOAT : \ + (size) == sizeof(double) ? _CFFI_PRIM_DOUBLE : \ + (size) == sizeof(long double) ? _CFFI__UNKNOWN_LONG_DOUBLE : \ + _CFFI__UNKNOWN_FLOAT_PRIM) + #define _cffi_check_int(got, got_nonpos, expected) \ ((got_nonpos) == (expected <= 0) && \ (got) == (unsigned long long)expected) diff --git a/lib_pypy/cffi/cffi_opcode.py b/lib_pypy/cffi/cffi_opcode.py --- a/lib_pypy/cffi/cffi_opcode.py +++ b/lib_pypy/cffi/cffi_opcode.py @@ -106,7 +106,9 @@ PRIM_UINTMAX = 47 _NUM_PRIM = 48 -_UNKNOWN_PRIM = -1 +_UNKNOWN_PRIM = -1 +_UNKNOWN_FLOAT_PRIM = -2 +_UNKNOWN_LONG_DOUBLE = -3 PRIMITIVE_TO_INDEX = { 'char': PRIM_CHAR, diff --git a/lib_pypy/cffi/cparser.py b/lib_pypy/cffi/cparser.py --- a/lib_pypy/cffi/cparser.py +++ b/lib_pypy/cffi/cparser.py @@ -15,9 +15,11 @@ except ImportError: lock = None -_r_comment = re.compile(r"/\*.*?\*/|//.*?$", re.DOTALL | re.MULTILINE) -_r_define = re.compile(r"^\s*#\s*define\s+([A-Za-z_][A-Za-z_0-9]*)\s+(.*?)$", - re.MULTILINE) +_r_comment = re.compile(r"/\*.*?\*/|//([^\n\\]|\\.)*?$", + re.DOTALL | re.MULTILINE) +_r_define = re.compile(r"^\s*#\s*define\s+([A-Za-z_][A-Za-z_0-9]*)" + r"\b((?:[^\n\\]|\\.)*?)$", + re.DOTALL | re.MULTILINE) _r_partial_enum = re.compile(r"=\s*\.\.\.\s*[,}]|\.\.\.\s*\}") _r_enum_dotdotdot = re.compile(r"__dotdotdot\d+__$") _r_partial_array = re.compile(r"\[\s*\.\.\.\s*\]") @@ -39,6 +41,7 @@ macros = {} for match in _r_define.finditer(csource): macroname, macrovalue = match.groups() + macrovalue = macrovalue.replace('\\\n', '').strip() macros[macroname] = macrovalue csource = _r_define.sub('', csource) # Replace "[...]" with "[__dotdotdotarray__]" @@ -423,13 +426,10 @@ raise api.CDefError( "%s: a function with only '(...)' as argument" " is not correct C" % (funcname or 'in expression')) - elif (len(params) == 1 and - isinstance(params[0].type, pycparser.c_ast.TypeDecl) and - isinstance(params[0].type.type, pycparser.c_ast.IdentifierType) - and list(params[0].type.type.names) == ['void']): - del params[0] args = [self._as_func_arg(self._get_type(argdeclnode.type)) for argdeclnode in params] + if not ellipsis and args == [model.void_type]: + args = [] result = self._get_type(typenode.type) return model.RawFunctionType(tuple(args), result, ellipsis) @@ -648,10 +648,21 @@ assert typenames[-1] == '__dotdotdot__' if len(typenames) == 1: return model.unknown_type(decl.name) - for t in typenames[:-1]: - if t not in ['int', 'short', 'long', 'signed', 'unsigned', 'char']: - raise api.FFIError(':%d: bad usage of "..."' % decl.coord.line) + + if (typenames[:-1] == ['float'] or + typenames[:-1] == ['double']): + # not for 'long double' so far + result = model.UnknownFloatType(decl.name) + else: + for t in typenames[:-1]: + if t not in ['int', 'short', 'long', 'signed', + 'unsigned', 'char']: + raise api.FFIError(':%d: bad usage of "..."' % + decl.coord.line) + result = model.UnknownIntegerType(decl.name) + if self._uses_new_feature is None: self._uses_new_feature = "'typedef %s... %s'" % ( ' '.join(typenames[:-1]), decl.name) - return model.UnknownIntegerType(decl.name) + + return result diff --git a/lib_pypy/cffi/model.py b/lib_pypy/cffi/model.py --- a/lib_pypy/cffi/model.py +++ b/lib_pypy/cffi/model.py @@ -158,12 +158,23 @@ self.c_name_with_marker = name + '&' def is_integer_type(self): - return True # for now + return True def build_backend_type(self, ffi, finishlist): raise NotImplementedError("integer type '%s' can only be used after " "compilation" % self.name) +class UnknownFloatType(BasePrimitiveType): + _attrs_ = ('name', ) + + def __init__(self, name): + self.name = name + self.c_name_with_marker = name + '&' + + def build_backend_type(self, ffi, finishlist): + raise NotImplementedError("float type '%s' can only be used after " + "compilation" % self.name) + class BaseFunctionType(BaseType): _attrs_ = ('args', 'result', 'ellipsis') diff --git a/lib_pypy/cffi/parse_c_type.h b/lib_pypy/cffi/parse_c_type.h --- a/lib_pypy/cffi/parse_c_type.h +++ b/lib_pypy/cffi/parse_c_type.h @@ -79,7 +79,9 @@ #define _CFFI_PRIM_UINTMAX 47 #define _CFFI__NUM_PRIM 48 -#define _CFFI__UNKNOWN_PRIM (-1) +#define _CFFI__UNKNOWN_PRIM (-1) +#define _CFFI__UNKNOWN_FLOAT_PRIM (-2) +#define _CFFI__UNKNOWN_LONG_DOUBLE (-3) struct _cffi_global_s { diff --git a/lib_pypy/cffi/recompiler.py b/lib_pypy/cffi/recompiler.py --- a/lib_pypy/cffi/recompiler.py +++ b/lib_pypy/cffi/recompiler.py @@ -4,11 +4,6 @@ VERSION = "0x2601" -try: - int_type = (int, long) -except NameError: # Python 3 - int_type = int - class GlobalExpr: def __init__(self, name, address, type_op, size=0, check_value=0): @@ -473,6 +468,10 @@ if tp.is_integer_type() and tp.name != '_Bool': converter = '_cffi_to_c_int' extraarg = ', %s' % tp.name + elif isinstance(tp, model.UnknownFloatType): + # don't check with is_float_type(): it may be a 'long + # double' here, and _cffi_to_c_double would loose precision + converter = '(%s)_cffi_to_c_double' % (tp.get_c_name(''),) else: converter = '(%s)_cffi_to_c_%s' % (tp.get_c_name(''), tp.name.replace(' ', '_')) @@ -527,6 +526,8 @@ if isinstance(tp, model.BasePrimitiveType): if tp.is_integer_type(): return '_cffi_from_c_int(%s, %s)' % (var, tp.name) + elif isinstance(tp, model.UnknownFloatType): + return '_cffi_from_c_double(%s)' % (var,) elif tp.name != 'long double': return '_cffi_from_c_%s(%s)' % (tp.name.replace(' ', '_'), var) else: @@ -1112,6 +1113,12 @@ ' ) <= 0)' % (tp.name, tp.name, tp.name)) self.cffi_types[index] = CffiOp(OP_PRIMITIVE, s) + def _emit_bytecode_UnknownFloatType(self, tp, index): + s = ('_cffi_prim_float(sizeof(%s) *\n' + ' (((%s)1) / 2) * 2 /* integer => 0, float => 1 */\n' + ' )' % (tp.name, tp.name)) + self.cffi_types[index] = CffiOp(OP_PRIMITIVE, s) + def _emit_bytecode_RawFunctionType(self, tp, index): self.cffi_types[index] = CffiOp(OP_FUNCTION, self._typesdict[tp.result]) index += 1 diff --git a/lib_pypy/cffi/setuptools_ext.py b/lib_pypy/cffi/setuptools_ext.py --- a/lib_pypy/cffi/setuptools_ext.py +++ b/lib_pypy/cffi/setuptools_ext.py @@ -81,10 +81,16 @@ allsources.extend(kwds.pop('sources', [])) ext = Extension(name=module_name, sources=allsources, **kwds) - def make_mod(tmpdir): + def make_mod(tmpdir, pre_run=None): c_file = os.path.join(tmpdir, module_name + source_extension) log.info("generating cffi module %r" % c_file) mkpath(tmpdir) + # a setuptools-only, API-only hook: called with the "ext" and "ffi" + # arguments just before we turn the ffi into C code. To use it, + # subclass the 'distutils.command.build_ext.build_ext' class and + # add a method 'def pre_run(self, ext, ffi)'. + if pre_run is not None: + pre_run(ext, ffi) updated = recompiler.make_c_source(ffi, module_name, source, c_file) if not updated: log.info("already up-to-date") @@ -98,7 +104,8 @@ class build_ext_make_mod(base_class): def run(self): if ext.sources[0] == '$PLACEHOLDER': - ext.sources[0] = make_mod(self.build_temp) + pre_run = getattr(self, 'pre_run', None) + ext.sources[0] = make_mod(self.build_temp, pre_run) base_class.run(self) dist.cmdclass['build_ext'] = build_ext_make_mod # NB. multiple runs here will create multiple 'build_ext_make_mod' diff --git a/lib_pypy/ctypes_support.py b/lib_pypy/ctypes_support.py --- a/lib_pypy/ctypes_support.py +++ b/lib_pypy/ctypes_support.py @@ -28,7 +28,7 @@ def _where_is_errno(): return standard_c_lib.__errno_location() -elif sys.platform in ('darwin', 'freebsd7', 'freebsd8', 'freebsd9'): +elif sys.platform == 'darwin' or sys.platform.startswith('freebsd'): standard_c_lib.__error.restype = ctypes.POINTER(ctypes.c_int) standard_c_lib.__error.argtypes = None def _where_is_errno(): diff --git a/lib_pypy/greenlet.egg-info b/lib_pypy/greenlet.egg-info --- a/lib_pypy/greenlet.egg-info +++ b/lib_pypy/greenlet.egg-info @@ -1,6 +1,6 @@ Metadata-Version: 1.0 Name: greenlet -Version: 0.4.7 +Version: 0.4.9 Summary: Lightweight in-process concurrent programming Home-page: https://github.com/python-greenlet/greenlet Author: Ralf Schmitt (for CPython), PyPy team diff --git a/lib_pypy/greenlet.py b/lib_pypy/greenlet.py --- a/lib_pypy/greenlet.py +++ b/lib_pypy/greenlet.py @@ -1,7 +1,7 @@ import sys import _continuation -__version__ = "0.4.7" +__version__ = "0.4.9" # ____________________________________________________________ # Exceptions diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py --- a/pypy/config/pypyoption.py +++ b/pypy/config/pypyoption.py @@ -39,7 +39,8 @@ "_csv", "cppyy", "_pypyjson" ]) -if sys.platform.startswith('linux') and os.uname()[4] == 'x86_64': +if (sys.platform.startswith('linux') and os.uname()[4] == 'x86_64' + and sys.maxint > 2**32): # it's not enough that we get x86_64 working_modules.add('_vmprof') translation_modules = default_modules.copy() diff --git a/pypy/doc/conf.py b/pypy/doc/conf.py --- a/pypy/doc/conf.py +++ b/pypy/doc/conf.py @@ -67,7 +67,7 @@ # The short X.Y version. version = '2.6' # The full version, including alpha/beta/rc tags. -release = '2.6.0' +release = '2.6.1' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/pypy/doc/contributor.rst b/pypy/doc/contributor.rst --- a/pypy/doc/contributor.rst +++ b/pypy/doc/contributor.rst @@ -32,6 +32,7 @@ Lukas Diekmann Sven Hager Anders Lehmann + Richard Plangger Aurelien Campeas Remi Meier Niklaus Haldimann @@ -57,7 +58,6 @@ Ludovic Aubry Jacob Hallen Jason Creighton - Richard Plangger Alex Martelli Michal Bendowski stian @@ -138,7 +138,6 @@ Michael Twomey Lucian Branescu Mihaila Yichao Yu - Anton Gulenko Gabriel Lavoie Olivier Dormond Jared Grubb @@ -185,6 +184,7 @@ Carl Meyer Karl Ramm Pieter Zieschang + Anton Gulenko Gabriel Lukas Vacek Andrew Dalke @@ -217,6 +217,7 @@ Toni Mattis Lucas Stadler Julian Berman + Markus Holtermann roberto@goyle Yury V. Zaytsev Anna Katrina Dominguez @@ -252,6 +253,7 @@ shoma hosaka Daniel Neuhäuser Ben Mather + Niclas Olofsson halgari Boglarka Vezer Chris Pressey diff --git a/pypy/doc/how-to-release.rst b/pypy/doc/how-to-release.rst --- a/pypy/doc/how-to-release.rst +++ b/pypy/doc/how-to-release.rst @@ -31,15 +31,14 @@ and add the new file to pypy/doc/index-of-whatsnew.rst * go to pypy/tool/release and run ``force-builds.py <release branch>`` - The following binaries should be built, however, we need more buildbots - - JIT: windows, linux, os/x, armhf, armel - - no JIT: windows, linux, os/x - - sandbox: linux, os/x + The following JIT binaries should be built, however, we need more buildbots + windows, linux-32, linux-64, osx64, armhf-raring, armhf-raspberrian, armel, + freebsd64 * wait for builds to complete, make sure there are no failures * download the builds, repackage binaries. Tag the release version and download and repackage source from bitbucket. You may find it - convenient to use the ``repackage.sh`` script in pypy/tools to do this. + convenient to use the ``repackage.sh`` script in pypy/tool/release to do this. Otherwise repackage and upload source "-src.tar.bz2" to bitbucket and to cobra, as some packagers prefer a clearly labeled source package diff --git a/pypy/doc/index-of-release-notes.rst b/pypy/doc/index-of-release-notes.rst --- a/pypy/doc/index-of-release-notes.rst +++ b/pypy/doc/index-of-release-notes.rst @@ -6,6 +6,7 @@ .. toctree:: + release-2.6.1.rst release-2.6.0.rst release-2.5.1.rst release-2.5.0.rst diff --git a/pypy/doc/release-2.6.1.rst b/pypy/doc/release-2.6.1.rst new file mode 100644 --- /dev/null +++ b/pypy/doc/release-2.6.1.rst @@ -0,0 +1,129 @@ +========== +PyPy 2.6.1 +========== + +We're pleased to announce PyPy 2.6.1, an update to PyPy 2.6.0 released June 1. +We have updated stdlib to 2.7.10, `cffi`_ to version 1.3, extended support for +the new vmprof_ statistical profiler for multiple threads, and increased +functionality of numpy. + +You can download the PyPy 2.6.1 release here: + + http://pypy.org/download.html + +We would like to thank our donors for the continued support of the PyPy +project, and our volunteers and contributors. + +.. _`cffi`: https://cffi.readthedocs.org + +We would also like to encourage new people to join the project. PyPy has many +layers and we need help with all of them: `PyPy`_ and `RPython`_ documentation +improvements, tweaking popular `modules`_ to run on pypy, or general `help`_ with making +RPython's JIT even better. + +.. _`PyPy`: http://doc.pypy.org +.. _`RPython`: https://rpython.readthedocs.org +.. _`modules`: http://doc.pypy.org/en/latest/project-ideas.html#make-more-python-modules-pypy-friendly +.. _`help`: http://doc.pypy.org/en/latest/project-ideas.html + +What is PyPy? +============= + +PyPy is a very compliant Python interpreter, almost a drop-in replacement for +CPython 2.7. It's fast (`pypy and cpython 2.7.x`_ performance comparison) +due to its integrated tracing JIT compiler. + +This release supports **x86** machines on most common operating systems +(Linux 32/64, Mac OS X 64, Windows 32, OpenBSD_, freebsd_), +as well as newer **ARM** hardware (ARMv6 or ARMv7, with VFPv3) running Linux. + +We also welcome developers of other +`dynamic languages`_ to see what RPython can do for them. + +.. _`pypy and cpython 2.7.x`: http://speed.pypy.org +.. _OpenBSD: http://cvsweb.openbsd.org/cgi-bin/cvsweb/ports/lang/pypy +.. _freebsd: https://svnweb.freebsd.org/ports/head/lang/pypy/ +.. _`dynamic languages`: http://pypyjs.org + +Highlights +=========== + +* Bug Fixes + + * Revive non-SSE2 support + + * Fixes for detaching _io.Buffer* + + * On Windows, close (and flush) all open sockets on exiting + + * Drop support for ancient macOS v10.4 and before + + * Clear up contention in the garbage collector between trace-me-later and pinning + + * Issues reported with our previous release were resolved_ after reports from users on + our issue tracker at https://bitbucket.org/pypy/pypy/issues or on IRC at + #pypy. + +* New features: + + * cffi was updated to version 1.3 + + * The python stdlib was updated to 2.7.10 from 2.7.9 + + * vmprof now supports multiple threads and OS X + + * The translation process builds cffi import libraries for some stdlib + packages, which should prevent confusion when package.py is not used + + * better support for gdb debugging + + * freebsd should be able to translate PyPy "out of the box" with no patches + +* Numpy: + + * Better support for record dtypes, including the ``align`` keyword + + * Implement casting and create output arrays accordingly (still missing some corner cases) + + * Support creation of unicode ndarrays + + * Better support ndarray.flags + + * Support ``axis`` argument in more functions + + * Refactor array indexing to support ellipses + + * Allow the docstrings of built-in numpy objects to be set at run-time + + * Support the ``buffered`` nditer creation keyword + +* Performance improvements: + + * Delay recursive calls to make them non-recursive + + * Skip loop unrolling if it compiles too much code + + * Tweak the heapcache + + * Add a list strategy for lists that store both floats and 32-bit integers. + The latter are encoded as nonstandard NaNs. Benchmarks show that the speed + of such lists is now very close to the speed of purely-int or purely-float + lists. + + * Simplify implementation of ffi.gc() to avoid most weakrefs + + * Massively improve the performance of map() with more than + one sequence argument + +.. _`vmprof`: https://vmprof.readthedocs.org +.. _resolved: http://doc.pypy.org/en/latest/whatsnew-2.6.1.html + +Please try it out and let us know what you think. We welcome +success stories, `experiments`_, or `benchmarks`_, we know you are using PyPy, please tell us about it! + +Cheers + +The PyPy Team + +.. _`experiments`: https://morepypy.blogspot.com/2015/02/experiments-in-pyrlang-with-rpython.html +.. _`benchmarks`: https://mithrandi.net/blog/2015/03/axiom-benchmark-results-on-pypy-2-5-0 diff --git a/pypy/doc/whatsnew-2.6.1.rst b/pypy/doc/whatsnew-2.6.1.rst --- a/pypy/doc/whatsnew-2.6.1.rst +++ b/pypy/doc/whatsnew-2.6.1.rst @@ -32,7 +32,10 @@ ``lst[0]`` is still *not* the float ``42.0`` but the integer ``42``.) .. branch: cffi-callback-onerror +Part of cffi 1.2. + .. branch: cffi-new-allocator +Part of cffi 1.2. .. branch: unicode-dtype @@ -67,3 +70,7 @@ .. branch: vmprof-review Clean up of vmprof, notably to handle correctly multiple threads + +.. branch: no_boehm_dl + +Remove extra link library from Boehm GC 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 @@ -3,5 +3,5 @@ ======================= .. this is a revision shortly after release-2.6.1 -.. startrev: 83ebc73d4fcb +.. startrev: 07769be4057b diff --git a/pypy/interpreter/miscutils.py b/pypy/interpreter/miscutils.py --- a/pypy/interpreter/miscutils.py +++ b/pypy/interpreter/miscutils.py @@ -9,6 +9,7 @@ implementation for this feature, and patches 'space.threadlocals' when 'thread' is initialized. """ + _immutable_fields_ = ['_value?'] _value = None def get_ec(self): diff --git a/pypy/module/_cffi_backend/__init__.py b/pypy/module/_cffi_backend/__init__.py --- a/pypy/module/_cffi_backend/__init__.py +++ b/pypy/module/_cffi_backend/__init__.py @@ -2,7 +2,7 @@ from pypy.interpreter.mixedmodule import MixedModule from rpython.rlib import rdynload -VERSION = "1.2.0" +VERSION = "1.3.0" class Module(MixedModule): diff --git a/pypy/module/_cffi_backend/cffi_opcode.py b/pypy/module/_cffi_backend/cffi_opcode.py --- a/pypy/module/_cffi_backend/cffi_opcode.py +++ b/pypy/module/_cffi_backend/cffi_opcode.py @@ -9,16 +9,16 @@ assert isinstance(self.arg, str) return '(_cffi_opcode_t)(%s)' % (self.arg,) classname = CLASS_NAME[self.op] - return '_CFFI_OP(_CFFI_OP_%s, %d)' % (classname, self.arg) + return '_CFFI_OP(_CFFI_OP_%s, %s)' % (classname, self.arg) def as_python_bytes(self): - if self.op is None: - if self.arg.isdigit(): - value = int(self.arg) # non-negative: '-' not in self.arg - if value >= 2**31: - raise OverflowError("cannot emit %r: limited to 2**31-1" - % (self.arg,)) - return format_four_bytes(value) + if self.op is None and self.arg.isdigit(): + value = int(self.arg) # non-negative: '-' not in self.arg + if value >= 2**31: + raise OverflowError("cannot emit %r: limited to 2**31-1" + % (self.arg,)) + return format_four_bytes(value) + if isinstance(self.arg, str): from .ffiplatform import VerificationError raise VerificationError("cannot emit to Python: %r" % (self.arg,)) return format_four_bytes((self.arg << 8) | self.op) @@ -106,7 +106,9 @@ PRIM_UINTMAX = 47 _NUM_PRIM = 48 -_UNKNOWN_PRIM = -1 +_UNKNOWN_PRIM = -1 +_UNKNOWN_FLOAT_PRIM = -2 +_UNKNOWN_LONG_DOUBLE = -3 PRIMITIVE_TO_INDEX = { 'char': PRIM_CHAR, diff --git a/pypy/module/_cffi_backend/realize_c_type.py b/pypy/module/_cffi_backend/realize_c_type.py --- a/pypy/module/_cffi_backend/realize_c_type.py +++ b/pypy/module/_cffi_backend/realize_c_type.py @@ -81,6 +81,13 @@ if num == cffi_opcode._UNKNOWN_PRIM: raise oefmt(ffi.w_FFIError, "primitive integer type with an " "unexpected size (or not an integer type at all)") + elif num == cffi_opcode._UNKNOWN_FLOAT_PRIM: + raise oefmt(ffi.w_FFIError, "primitive floating-point type with an " + "unexpected size (or not a float type at all)") + elif num == cffi_opcode._UNKNOWN_LONG_DOUBLE: + raise oefmt(ffi.w_FFIError, "primitive floating-point type is " + "'long double', not supported for now with " + "the syntax 'typedef double... xxx;'") else: raise oefmt(space.w_NotImplementedError, "prim=%d", num) realize_cache = space.fromcache(RealizeCache) diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py --- a/pypy/module/_cffi_backend/test/_backend_test_c.py +++ b/pypy/module/_cffi_backend/test/_backend_test_c.py @@ -1,6 +1,9 @@ # ____________________________________________________________ import sys +assert __version__ == "1.3.0", ("This test_c.py file is for testing a version" + " of cffi that differs from the one that we" + " get from 'import _cffi_backend'") if sys.version_info < (3,): type_or_class = "type" mandatory_b_prefix = '' @@ -3424,7 +3427,3 @@ "be 'foo *', but the types are different (check " "that you are not e.g. mixing up different ffi " "instances)") - -def test_version(): - # this test is here mostly for PyPy - assert __version__ == "1.2.0" diff --git a/pypy/module/_multiprocessing/test/test_memory.py b/pypy/module/_multiprocessing/test/test_memory.py --- a/pypy/module/_multiprocessing/test/test_memory.py +++ b/pypy/module/_multiprocessing/test/test_memory.py @@ -1,8 +1,12 @@ +import sys + class AppTestMemory: spaceconfig = dict(usemodules=('_multiprocessing', 'mmap', '_rawffi', 'itertools', - 'signal', 'select', 'fcntl', + 'signal', 'select', 'binascii')) + if sys.platform != 'win32': + spaceconfig['usemodules'] += ('fcntl',) def test_address_of(self): import _multiprocessing diff --git a/pypy/module/_multiprocessing/test/test_semaphore.py b/pypy/module/_multiprocessing/test/test_semaphore.py --- a/pypy/module/_multiprocessing/test/test_semaphore.py +++ b/pypy/module/_multiprocessing/test/test_semaphore.py @@ -1,12 +1,19 @@ +import sys + from pypy.module._multiprocessing.interp_semaphore import ( RECURSIVE_MUTEX, SEMAPHORE) class AppTestSemaphore: spaceconfig = dict(usemodules=('_multiprocessing', 'thread', - 'signal', 'select', 'fcntl', + 'signal', 'select', 'binascii', 'struct')) + if sys.platform == 'win32': + spaceconfig['usemodules'] += ('_rawffi',) + else: + spaceconfig['usemodules'] += ('fcntl',) + def setup_class(cls): cls.w_SEMAPHORE = cls.space.wrap(SEMAPHORE) cls.w_RECURSIVE = cls.space.wrap(RECURSIVE_MUTEX) diff --git a/pypy/module/cpyext/include/object.h b/pypy/module/cpyext/include/object.h --- a/pypy/module/cpyext/include/object.h +++ b/pypy/module/cpyext/include/object.h @@ -379,6 +379,8 @@ PyObject *ht_name, *ht_slots; } PyHeapTypeObject; +#define PyObject_Bytes PyObject_Str + /* Flag bits for printing: */ #define Py_PRINT_RAW 1 /* No string quotes etc. */ diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_parsing.py b/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_parsing.py --- a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_parsing.py +++ b/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_parsing.py @@ -160,6 +160,35 @@ assert func.name == 'sin' assert func.BType == '<func (<double>, <double>), <double>, False>' +def test_remove_line_continuation_comments(): + ffi = FFI(backend=FakeBackend()) + ffi.cdef(""" + double // blah \\ + more comments + x(void); + double // blah\\\\ + y(void); + double // blah\\ \ + etc + z(void); + """) + m = ffi.dlopen(lib_m) + m.x + m.y + m.z + +def test_line_continuation_in_defines(): + ffi = FFI(backend=FakeBackend()) + ffi.cdef(""" + #define ABC\\ + 42 + #define BCD \\ + 43 + """) + m = ffi.dlopen(lib_m) + assert m.ABC == 42 + assert m.BCD == 43 + def test_define_not_supported_for_now(): ffi = FFI(backend=FakeBackend()) e = py.test.raises(CDefError, ffi.cdef, '#define FOO "blah"') @@ -238,6 +267,13 @@ ffi = FFI() ffi.cdef("typedef _Bool bool; void f(bool);") +def test_void_renamed_as_only_arg(): + ffi = FFI() + ffi.cdef("typedef void void_t1;" + "typedef void_t1 void_t;" + "typedef int (*func_t)(void_t);") + assert ffi.typeof("func_t").args == () + def test_win_common_types(): from cffi.commontypes import COMMON_TYPES, _CACHE from cffi.commontypes import win_common_types, resolve_common_type diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py --- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py +++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py @@ -1,7 +1,7 @@ # Generated by pypy/tool/import_cffi.py import sys, os, py -from cffi import FFI, VerificationError +from cffi import FFI, VerificationError, FFIError from cffi import recompiler from pypy.module.test_lib_pypy.cffi_tests.udir import udir from pypy.module.test_lib_pypy.cffi_tests.support import u @@ -25,6 +25,9 @@ if 1: # test the .cpp mode too kwds.setdefault('source_extension', '.cpp') source = 'extern "C" {\n%s\n}' % (source,) + else: + kwds['extra_compile_args'] = (kwds.get('extra_compile_args', []) + + ['-Werror']) return recompiler._verify(ffi, module_name, source, *args, **kwds) @@ -1054,14 +1057,54 @@ assert lib.nu == 20 def test_some_float_type(): - py.test.skip("later") ffi = FFI() - ffi.cdef("typedef double... foo_t; foo_t sum(foo_t[]);") + ffi.cdef(""" + typedef double... foo_t; + typedef float... bar_t; + foo_t sum(foo_t[]); + bar_t neg(bar_t); + """) lib = verify(ffi, 'test_some_float_type', """ typedef float foo_t; static foo_t sum(foo_t x[]) { return x[0] + x[1]; } + typedef double bar_t; + static double neg(double x) { return -x; } """) assert lib.sum([40.0, 2.25]) == 42.25 + assert lib.sum([12.3, 45.6]) != 12.3 + 45.6 # precision loss + assert lib.neg(12.3) == -12.3 # no precision loss + assert ffi.sizeof("foo_t") == ffi.sizeof("float") + assert ffi.sizeof("bar_t") == ffi.sizeof("double") + +def test_some_float_invalid_1(): + ffi = FFI() + py.test.raises(FFIError, ffi.cdef, "typedef long double... foo_t;") + +def test_some_float_invalid_2(): + ffi = FFI() + ffi.cdef("typedef double... foo_t; foo_t neg(foo_t);") + lib = verify(ffi, 'test_some_float_invalid_2', """ + typedef unsigned long foo_t; + foo_t neg(foo_t x) { return -x; } + """) + e = py.test.raises(ffi.error, getattr, lib, 'neg') + assert str(e.value) == ("primitive floating-point type with an unexpected " + "size (or not a float type at all)") + +def test_some_float_invalid_3(): + ffi = FFI() + ffi.cdef("typedef double... foo_t; foo_t neg(foo_t);") + lib = verify(ffi, 'test_some_float_invalid_3', """ + typedef long double foo_t; + foo_t neg(foo_t x) { return -x; } + """) + if ffi.sizeof("long double") == ffi.sizeof("double"): + assert lib.neg(12.3) == -12.3 + else: + e = py.test.raises(ffi.error, getattr, lib, 'neg') + assert str(e.value) == ("primitive floating-point type is " + "'long double', not supported for now with " + "the syntax 'typedef double... xxx;'") def test_issue200(): ffi = FFI() diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_zdist.py b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_zdist.py --- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_zdist.py +++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_zdist.py @@ -318,15 +318,32 @@ import cffi ffi = cffi.FFI() ffi.set_source("pack3.mymod", "/*code would be here*/") + ffi._hi_there = 42 """) with open("setup.py", "w") as f: - f.write("""if 1: + f.write("from __future__ import print_function\n" + """if 1: from setuptools import setup + from distutils.command.build_ext import build_ext + import os + + class TestBuildExt(build_ext): + def pre_run(self, ext, ffi): + print('_make_setuptools_api: in pre_run:', end=" ") + assert ffi._hi_there == 42 + assert ext.name == "pack3.mymod" + fn = os.path.join(os.path.dirname(self.build_lib), + '..', 'see_me') + print('creating %r' % (fn,)) + open(fn, 'w').close() + setup(name='example1', version='0.1', packages=['pack3'], package_dir={'': 'src1'}, - cffi_modules=["src1/pack3/_build.py:ffi"]) + cffi_modules=["src1/pack3/_build.py:ffi"], + cmdclass={'build_ext': TestBuildExt}, + ) """) @chdir_to_tmp @@ -335,6 +352,7 @@ self.run(["setup.py", "build"]) self.check_produced_files({'setup.py': None, 'build': '?', + 'see_me': None, 'src1': {'pack3': {'__init__.py': None, '_build.py': None}}}) @@ -344,6 +362,7 @@ self.run(["setup.py", "build_ext", "-i"]) self.check_produced_files({'setup.py': None, 'build': '?', + 'see_me': None, 'src1': {'pack3': {'__init__.py': None, '_build.py': None, 'mymod.SO': None}}}) diff --git a/pypy/module/thread/test/test_lock.py b/pypy/module/thread/test/test_lock.py --- a/pypy/module/thread/test/test_lock.py +++ b/pypy/module/thread/test/test_lock.py @@ -116,9 +116,6 @@ class AppTestLockSignals(GenericTestThread): pytestmark = py.test.mark.skipif("os.name != 'posix'") - def setup_class(cls): - cls.w_using_pthread_cond = cls.space.wrap(sys.platform == 'freebsd6') - def w_acquire_retries_on_intr(self, lock): import thread, os, signal, time self.sig_recvd = False @@ -157,8 +154,6 @@ raise KeyboardInterrupt def test_lock_acquire_interruption(self): - if self.using_pthread_cond: - skip('POSIX condition variables cannot be interrupted') import thread, signal, time # Mimic receiving a SIGINT (KeyboardInterrupt) with SIGALRM while stuck # in a deadlock. diff --git a/pypy/objspace/std/celldict.py b/pypy/objspace/std/celldict.py --- a/pypy/objspace/std/celldict.py +++ b/pypy/objspace/std/celldict.py @@ -3,7 +3,7 @@ indirection is introduced to make the version tag change less often. """ -from rpython.rlib import jit, rerased +from rpython.rlib import jit, rerased, objectmodel from pypy.interpreter.baseobjspace import W_Root from pypy.objspace.std.dictmultiobject import ( @@ -162,8 +162,8 @@ def getitervalues(self, w_dict): return self.unerase(w_dict.dstorage).itervalues() - def getiteritems(self, w_dict): - return self.unerase(w_dict.dstorage).iteritems() + def getiteritems_with_hash(self, w_dict): + return objectmodel.iteritems_with_hash(self.unerase(w_dict.dstorage)) wrapkey = _wrapkey diff --git a/pypy/objspace/std/dictmultiobject.py b/pypy/objspace/std/dictmultiobject.py --- a/pypy/objspace/std/dictmultiobject.py +++ b/pypy/objspace/std/dictmultiobject.py @@ -511,7 +511,7 @@ def getitervalues(self, w_dict): raise NotImplementedError - def getiteritems(self, w_dict): + def getiteritems_with_hash(self, w_dict): raise NotImplementedError has_iterreversed = False @@ -634,7 +634,7 @@ def getitervalues(self, w_dict): return iter([]) - def getiteritems(self, w_dict): + def getiteritems_with_hash(self, w_dict): return iter([]) def getiterreversed(self, w_dict): @@ -751,11 +751,11 @@ class IterClassItems(BaseItemIterator): def __init__(self, space, strategy, impl): - self.iterator = strategy.getiteritems(impl) + self.iterator = strategy.getiteritems_with_hash(impl) BaseIteratorImplementation.__init__(self, space, strategy, impl) def next_item_entry(self): - for key, value in self.iterator: + for key, value, keyhash in self.iterator: return (wrapkey(self.space, key), wrapvalue(self.space, value)) else: @@ -793,10 +793,10 @@ # the logic is to call prepare_dict_update() after the first setitem(): # it gives the w_updatedict a chance to switch its strategy. if 1: # (preserve indentation) - iteritems = self.getiteritems(w_dict) + iteritemsh = self.getiteritems_with_hash(w_dict) if not same_strategy(self, w_updatedict): # Different strategy. Try to copy one item of w_dict - for key, value in iteritems: + for key, value, keyhash in iteritemsh: w_key = wrapkey(self.space, key) w_value = wrapvalue(self.space, value) w_updatedict.setitem(w_key, w_value) @@ -807,7 +807,7 @@ w_updatedict.strategy.prepare_update(w_updatedict, count) # If the strategy is still different, continue the slow way if not same_strategy(self, w_updatedict): - for key, value in iteritems: + for key, value, keyhash in iteritemsh: w_key = wrapkey(self.space, key) w_value = wrapvalue(self.space, value) w_updatedict.setitem(w_key, w_value) @@ -820,8 +820,8 @@ # wrapping/unwrapping the key. assert setitem_untyped is not None dstorage = w_updatedict.dstorage - for key, value in iteritems: - setitem_untyped(self, dstorage, key, value) + for key, value, keyhash in iteritemsh: + setitem_untyped(self, dstorage, key, value, keyhash) def same_strategy(self, w_otherdict): return (setitem_untyped is not None and @@ -945,8 +945,8 @@ def getitervalues(self, w_dict): return self.unerase(w_dict.dstorage).itervalues() - def getiteritems(self, w_dict): - return self.unerase(w_dict.dstorage).iteritems() + def getiteritems_with_hash(self, w_dict): + return objectmodel.iteritems_with_hash(self.unerase(w_dict.dstorage)) def getiterreversed(self, w_dict): return objectmodel.reversed_dict(self.unerase(w_dict.dstorage)) @@ -955,8 +955,9 @@ objectmodel.prepare_dict_update(self.unerase(w_dict.dstorage), num_extra) - def setitem_untyped(self, dstorage, key, w_value): - self.unerase(dstorage)[key] = w_value + def setitem_untyped(self, dstorage, key, w_value, keyhash): + d = self.unerase(dstorage) + objectmodel.setitem_with_hash(d, key, keyhash, w_value) class ObjectDictStrategy(AbstractTypedStrategy, DictStrategy): diff --git a/pypy/objspace/std/dictproxyobject.py b/pypy/objspace/std/dictproxyobject.py --- a/pypy/objspace/std/dictproxyobject.py +++ b/pypy/objspace/std/dictproxyobject.py @@ -1,4 +1,5 @@ from rpython.rlib import rerased +from rpython.rlib.objectmodel import iteritems_with_hash from pypy.interpreter.error import OperationError, oefmt from pypy.objspace.std.dictmultiobject import ( @@ -103,8 +104,8 @@ return self.unerase(w_dict.dstorage).dict_w.iterkeys() def getitervalues(self, w_dict): return self.unerase(w_dict.dstorage).dict_w.itervalues() - def getiteritems(self, w_dict): - return self.unerase(w_dict.dstorage).dict_w.iteritems() + def getiteritems_with_hash(self, w_dict): + return iteritems_with_hash(self.unerase(w_dict.dstorage).dict_w) def wrapkey(space, key): return space.wrap(key) def wrapvalue(space, value): diff --git a/pypy/objspace/std/kwargsdict.py b/pypy/objspace/std/kwargsdict.py --- a/pypy/objspace/std/kwargsdict.py +++ b/pypy/objspace/std/kwargsdict.py @@ -3,7 +3,7 @@ Based on two lists containing unwrapped key value pairs. """ -from rpython.rlib import jit, rerased +from rpython.rlib import jit, rerased, objectmodel from pypy.objspace.std.dictmultiobject import ( BytesDictStrategy, DictStrategy, EmptyDictStrategy, ObjectDictStrategy, @@ -165,13 +165,14 @@ def getitervalues(self, w_dict): return iter(self.unerase(w_dict.dstorage)[1]) - def getiteritems(self, w_dict): - return Zip(*self.unerase(w_dict.dstorage)) + def getiteritems_with_hash(self, w_dict): + keys, values_w = self.unerase(w_dict.dstorage) + return ZipItemsWithHash(keys, values_w) wrapkey = _wrapkey -class Zip(object): +class ZipItemsWithHash(object): def __init__(self, list1, list2): assert len(list1) == len(list2) self.list1 = list1 @@ -186,6 +187,7 @@ if i >= len(self.list1): raise StopIteration self.i = i + 1 - return (self.list1[i], self.list2[i]) + key = self.list1[i] + return (key, self.list2[i], objectmodel.compute_hash(key)) create_iterator_classes(KwargsDictStrategy) diff --git a/pypy/objspace/std/setobject.py b/pypy/objspace/std/setobject.py --- a/pypy/objspace/std/setobject.py +++ b/pypy/objspace/std/setobject.py @@ -8,6 +8,8 @@ from pypy.objspace.std.unicodeobject import W_UnicodeObject from rpython.rlib.objectmodel import r_dict +from rpython.rlib.objectmodel import iterkeys_with_hash, contains_with_hash +from rpython.rlib.objectmodel import setitem_with_hash, delitem_with_hash from rpython.rlib.rarithmetic import intmask, r_uint from rpython.rlib import rerased, jit @@ -961,12 +963,12 @@ return self.erase(result_dict) def _difference_unwrapped(self, w_set, w_other): - iterator = self.unerase(w_set.sstorage).iterkeys() + self_dict = self.unerase(w_set.sstorage) other_dict = self.unerase(w_other.sstorage) result_dict = self.get_empty_dict() - for key in iterator: - if key not in other_dict: - result_dict[key] = None + for key, keyhash in iterkeys_with_hash(self_dict): + if not contains_with_hash(other_dict, key, keyhash): + setitem_with_hash(result_dict, key, keyhash, None) return self.erase(result_dict) def _difference_base(self, w_set, w_other): @@ -989,10 +991,10 @@ if w_set.sstorage is w_other.sstorage: my_dict.clear() return - iterator = self.unerase(w_other.sstorage).iterkeys() - for key in iterator: + other_dict = self.unerase(w_other.sstorage) + for key, keyhash in iterkeys_with_hash(other_dict): try: - del my_dict[key] + delitem_with_hash(my_dict, key, keyhash) except KeyError: pass @@ -1020,12 +1022,12 @@ d_new = self.get_empty_dict() d_this = self.unerase(w_set.sstorage) d_other = self.unerase(w_other.sstorage) - for key in d_other.keys(): - if not key in d_this: - d_new[key] = None - for key in d_this.keys(): - if not key in d_other: - d_new[key] = None + for key, keyhash in iterkeys_with_hash(d_other): + if not contains_with_hash(d_this, key, keyhash): + setitem_with_hash(d_new, key, keyhash, None) + for key, keyhash in iterkeys_with_hash(d_this): + if not contains_with_hash(d_other, key, keyhash): + setitem_with_hash(d_new, key, keyhash, None) storage = self.erase(d_new) return storage @@ -1105,9 +1107,9 @@ result = self.get_empty_dict() d_this = self.unerase(w_set.sstorage) d_other = self.unerase(w_other.sstorage) - for key in d_this: - if key in d_other: - result[key] = None + for key, keyhash in iterkeys_with_hash(d_this): + if contains_with_hash(d_other, key, keyhash): + setitem_with_hash(result, key, keyhash, None) return self.erase(result) def intersect(self, w_set, w_other): @@ -1125,9 +1127,10 @@ w_set.sstorage = storage def _issubset_unwrapped(self, w_set, w_other): + d_set = self.unerase(w_set.sstorage) d_other = self.unerase(w_other.sstorage) - for item in self.unerase(w_set.sstorage): - if not item in d_other: + for key, keyhash in iterkeys_with_hash(d_set): + if not contains_with_hash(d_other, key, keyhash): return False return True @@ -1152,8 +1155,8 @@ def _isdisjoint_unwrapped(self, w_set, w_other): d_set = self.unerase(w_set.sstorage) d_other = self.unerase(w_other.sstorage) - for key in d_set: - if key in d_other: + for key, keyhash in iterkeys_with_hash(d_set): + if contains_with_hash(d_other, key, keyhash): return False return True diff --git a/pypy/tool/release/force-builds.py b/pypy/tool/release/force-builds.py --- a/pypy/tool/release/force-builds.py +++ b/pypy/tool/release/force-builds.py @@ -28,6 +28,7 @@ # 'pypy-c-app-level-win-x86-32', 'pypy-c-jit-linux-x86-32', 'pypy-c-jit-linux-x86-64', + 'pypy-c-jit-freebsd-9-x86-64', 'pypy-c-jit-macosx-x86-64', 'pypy-c-jit-win-x86-32', 'build-pypy-c-jit-linux-armhf-raring', @@ -42,7 +43,7 @@ import pwd return pwd.getpwuid(os.getuid())[0] -def main(branch, server): +def main(branch, server, user): #XXX: handle release tags #XXX: handle validity checks lock = defer.DeferredLock() @@ -56,7 +57,7 @@ print 'Forcing', builder, '...' url = "http://" + server + "/builders/" + builder + "/force" args = [ - ('username', get_user()), + ('username', user), ('revision', ''), ('forcescheduler', 'Force Scheduler'), ('submit', 'Force Build'), @@ -78,7 +79,8 @@ parser = optparse.OptionParser() parser.add_option("-b", "--branch", help="branch to build", default='') parser.add_option("-s", "--server", help="buildbot server", default="buildbot.pypy.org") + parser.add_option("-u", "--user", help="user name to report", default=get_user()) (options, args) = parser.parse_args() if not options.branch: parser.error("branch option required") - main(options.branch, options.server) + main(options.branch, options.server, user=options.user) diff --git a/pypy/tool/release/repackage.sh b/pypy/tool/release/repackage.sh --- a/pypy/tool/release/repackage.sh +++ b/pypy/tool/release/repackage.sh @@ -1,12 +1,12 @@ # Edit these appropriately before running this script maj=2 min=6 -rev=0 +rev=1 # This script will download latest builds from the buildmaster, rename the top # level directory, and repackage ready to be uploaded to bitbucket. It will also # download source, assuming a tag for the release already exists, and repackage them. -for plat in linux linux64 linux-armhf-raspbian linux-armhf-raring linux-armel osx64 +for plat in linux linux64 linux-armhf-raspbian linux-armhf-raring linux-armel osx64 freebsd64 do wget http://buildbot.pypy.org/nightly/release-$maj.$min.x/pypy-c-jit-latest-$plat.tar.bz2 tar -xf pypy-c-jit-latest-$plat.tar.bz2 diff --git a/rpython/annotator/binaryop.py b/rpython/annotator/binaryop.py --- a/rpython/annotator/binaryop.py +++ b/rpython/annotator/binaryop.py @@ -520,26 +520,32 @@ return dic1.__class__(dic1.dictdef.union(dic2.dictdef)) +def _dict_can_only_throw_keyerror(s_dct, *ignore): + if s_dct.dictdef.dictkey.custom_eq_hash: + return None # r_dict: can throw anything + return [KeyError] + +def _dict_can_only_throw_nothing(s_dct, *ignore): + if s_dct.dictdef.dictkey.custom_eq_hash: + return None # r_dict: can throw anything + return [] # else: no possible exception + + class __extend__(pairtype(SomeDict, SomeObject)): - def _can_only_throw(dic1, *ignore): - if dic1.dictdef.dictkey.custom_eq_hash: - return None - return [KeyError] - def getitem((dic1, obj2)): dic1.dictdef.generalize_key(obj2) return dic1.dictdef.read_value() - getitem.can_only_throw = _can_only_throw + getitem.can_only_throw = _dict_can_only_throw_keyerror def setitem((dic1, obj2), s_value): dic1.dictdef.generalize_key(obj2) dic1.dictdef.generalize_value(s_value) - setitem.can_only_throw = _can_only_throw + setitem.can_only_throw = _dict_can_only_throw_nothing def delitem((dic1, obj2)): dic1.dictdef.generalize_key(obj2) - delitem.can_only_throw = _can_only_throw + delitem.can_only_throw = _dict_can_only_throw_keyerror class __extend__(pairtype(SomeTuple, SomeInteger)): diff --git a/rpython/annotator/unaryop.py b/rpython/annotator/unaryop.py --- a/rpython/annotator/unaryop.py +++ b/rpython/annotator/unaryop.py @@ -4,6 +4,7 @@ from __future__ import absolute_import +from rpython.tool.pairtype import pair from rpython.flowspace.operation import op from rpython.flowspace.model import const, Constant from rpython.flowspace.argument import CallSpec @@ -11,11 +12,13 @@ SomeString, SomeChar, SomeList, SomeDict, SomeTuple, SomeImpossibleValue, SomeUnicodeCodePoint, SomeInstance, SomeBuiltin, SomeBuiltinMethod, SomeFloat, SomeIterator, SomePBC, SomeNone, SomeType, s_ImpossibleValue, - s_Bool, s_None, unionof, add_knowntypedata, + s_Bool, s_None, s_Int, unionof, add_knowntypedata, HarmlesslyBlocked, SomeWeakRef, SomeUnicodeString, SomeByteArray) from rpython.annotator.bookkeeper import getbookkeeper, immutablevalue from rpython.annotator import builtin from rpython.annotator.binaryop import _clone ## XXX where to put this? +from rpython.annotator.binaryop import _dict_can_only_throw_keyerror +from rpython.annotator.binaryop import _dict_can_only_throw_nothing from rpython.annotator.model import AnnotatorError from rpython.annotator.argument import simple_args, complex_args @@ -364,20 +367,19 @@ raise AnnotatorError("%s: not proven to have non-negative stop" % error) -def _can_only_throw(s_dct, *ignore): - if s_dct.dictdef.dictkey.custom_eq_hash: - return None # r_dict: can throw anything - return [] # else: no possible exception - -@op.contains.register(SomeDict) -def contains_SomeDict(annotator, dct, element): - annotator.annotation(dct).dictdef.generalize_key(annotator.annotation(element)) - if annotator.annotation(dct)._is_empty(): +def dict_contains(s_dct, s_element): + s_dct.dictdef.generalize_key(s_element) + if s_dct._is_empty(): s_bool = SomeBool() s_bool.const = False return s_bool return s_Bool -contains_SomeDict.can_only_throw = _can_only_throw + +@op.contains.register(SomeDict) +def contains_SomeDict(annotator, dct, element): + return dict_contains(annotator.annotation(dct), + annotator.annotation(element)) +contains_SomeDict.can_only_throw = _dict_can_only_throw_nothing class __extend__(SomeDict): @@ -401,16 +403,22 @@ return self.dictdef.read_key() elif variant == 'values': return self.dictdef.read_value() - elif variant == 'items': + elif variant == 'items' or variant == 'items_with_hash': s_key = self.dictdef.read_key() s_value = self.dictdef.read_value() if (isinstance(s_key, SomeImpossibleValue) or isinstance(s_value, SomeImpossibleValue)): return s_ImpossibleValue - else: + elif variant == 'items': return SomeTuple((s_key, s_value)) - else: - raise ValueError + elif variant == 'items_with_hash': + return SomeTuple((s_key, s_value, s_Int)) + elif variant == 'keys_with_hash': + s_key = self.dictdef.read_key() + if isinstance(s_key, SomeImpossibleValue): + return s_ImpossibleValue + return SomeTuple((s_key, s_Int)) + raise ValueError(variant) def method_get(self, key, dfl): self.dictdef.generalize_key(key) @@ -448,6 +456,12 @@ def method_iteritems(self): return SomeIterator(self, 'items') + def method_iterkeys_with_hash(self): + return SomeIterator(self, 'keys_with_hash') + + def method_iteritems_with_hash(self): + return SomeIterator(self, 'items_with_hash') + def method_clear(self): pass @@ -460,6 +474,22 @@ self.dictdef.generalize_value(s_dfl) return self.dictdef.read_value() + def method_contains_with_hash(self, s_key, s_hash): + return dict_contains(self, s_key) + method_contains_with_hash.can_only_throw = _dict_can_only_throw_nothing + + def method_setitem_with_hash(self, s_key, s_hash, s_value): + pair(self, s_key).setitem(s_value) + method_setitem_with_hash.can_only_throw = _dict_can_only_throw_nothing + + def method_getitem_with_hash(self, s_key, s_hash): + return pair(self, s_key).getitem() + method_getitem_with_hash.can_only_throw = _dict_can_only_throw_keyerror + + def method_delitem_with_hash(self, s_key, s_hash): + pair(self, s_key).delitem() + method_delitem_with_hash.can_only_throw = _dict_can_only_throw_keyerror + @op.contains.register(SomeString) @op.contains.register(SomeUnicodeString) def contains_String(annotator, string, char): diff --git a/rpython/doc/conf.py b/rpython/doc/conf.py --- a/rpython/doc/conf.py +++ b/rpython/doc/conf.py @@ -68,7 +68,7 @@ # The short X.Y version. version = '2.6' # The full version, including alpha/beta/rc tags. -release = '2.6.0' +release = '2.6.1' # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. diff --git a/rpython/jit/backend/arm/runner.py b/rpython/jit/backend/arm/runner.py --- a/rpython/jit/backend/arm/runner.py +++ b/rpython/jit/backend/arm/runner.py @@ -64,12 +64,6 @@ operations, original_loop_token, log=log) - def clear_latest_values(self, count): - setitem = self.assembler.fail_boxes_ptr.setitem - null = lltype.nullptr(llmemory.GCREF.TO) - for index in range(count): - setitem(index, null) - def cast_ptr_to_int(x): adr = llmemory.cast_ptr_to_adr(x) return CPU_ARM.cast_adr_to_int(adr) diff --git a/rpython/jit/backend/llsupport/assembler.py b/rpython/jit/backend/llsupport/assembler.py --- a/rpython/jit/backend/llsupport/assembler.py +++ b/rpython/jit/backend/llsupport/assembler.py @@ -212,8 +212,7 @@ self.codemap_builder.leave_portal_frame(op.getarg(0).getint(), self.mc.get_relative_pos()) - def call_assembler(self, op, guard_op, argloc, vloc, result_loc, tmploc): - self._store_force_index(guard_op) + def call_assembler(self, op, argloc, vloc, result_loc, tmploc): descr = op.getdescr() assert isinstance(descr, JitCellToken) # @@ -262,9 +261,6 @@ # # Here we join Path A and Path B again self._call_assembler_patch_jmp(jmp_location) - # XXX here should be emitted guard_not_forced, but due - # to incompatibilities in how it's done, we leave it for the - # caller to deal with @specialize.argtype(1) def _inject_debugging_code(self, looptoken, operations, tp, number): diff --git a/rpython/jit/backend/llsupport/regalloc.py b/rpython/jit/backend/llsupport/regalloc.py --- a/rpython/jit/backend/llsupport/regalloc.py +++ b/rpython/jit/backend/llsupport/regalloc.py @@ -636,35 +636,29 @@ assert isinstance(box, Box) loc = self.fm.get_new_loc(box) locs.append(loc.value - base_ofs) - if looptoken.compiled_loop_token is not None: - # for tests + if looptoken.compiled_loop_token is not None: # <- for tests looptoken.compiled_loop_token._ll_initial_locs = locs - def can_merge_with_next_guard(self, op, i, operations): - if (op.getopnum() == rop.CALL_MAY_FORCE or - op.getopnum() == rop.CALL_ASSEMBLER or - op.getopnum() == rop.CALL_RELEASE_GIL): - assert operations[i + 1].getopnum() == rop.GUARD_NOT_FORCED - return True - if not op.is_comparison(): - if op.is_ovf(): - if (operations[i + 1].getopnum() != rop.GUARD_NO_OVERFLOW and - operations[i + 1].getopnum() != rop.GUARD_OVERFLOW): - not_implemented("int_xxx_ovf not followed by " - "guard_(no)_overflow") - return True + def next_op_can_accept_cc(self, operations, i): + op = operations[i] + next_op = operations[i + 1] + opnum = next_op.getopnum() + if (opnum != rop.GUARD_TRUE and opnum != rop.GUARD_FALSE + and opnum != rop.COND_CALL): return False - if (operations[i + 1].getopnum() != rop.GUARD_TRUE and - operations[i + 1].getopnum() != rop.GUARD_FALSE): + if next_op.getarg(0) is not op.result: return False - if operations[i + 1].getarg(0) is not op.result: + if self.longevity[op.result][1] > i + 1: return False - if (self.longevity[op.result][1] > i + 1 or - op.result in operations[i + 1].getfailargs()): - return False + if opnum != rop.COND_CALL: + if op.result in operations[i + 1].getfailargs(): + return False + else: + if op.result in operations[i + 1].getarglist()[1:]: + return False return True - def locs_for_call_assembler(self, op, guard_op): + def locs_for_call_assembler(self, op): descr = op.getdescr() assert isinstance(descr, JitCellToken) if op.numargs() == 2: diff --git a/rpython/jit/backend/test/runner_test.py b/rpython/jit/backend/test/runner_test.py --- a/rpython/jit/backend/test/runner_test.py +++ b/rpython/jit/backend/test/runner_test.py @@ -2315,7 +2315,7 @@ value |= 32768 assert s.data.tid == value - def test_cond_call(self): + def test_cond_call_1(self): def func_void(*args): called.append(args) @@ -2352,6 +2352,51 @@ assert longlong.getrealfloat(self.cpu.get_float_value(frame, 6)) == 1.2 assert longlong.getrealfloat(self.cpu.get_float_value(frame, 7)) == 3.4 + def test_cond_call_2(self): + def func_void(*args): + called.append(args) + + FUNC = self.FuncType([lltype.Signed, lltype.Signed], lltype.Void) + func_ptr = llhelper(lltype.Ptr(FUNC), func_void) + calldescr = self.cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT, + EffectInfo.MOST_GENERAL) + + for (operation, arg1, arg2_if_true, arg2_if_false) in [ + ('int_lt', -5, 2, -5), + ('int_le', 5, 5, -6), + ('int_eq', 11, 11, 12), + ('int_ne', 11, 12, 11), + ('int_gt', 8, -1, 8), + ('int_xor', 7, 3, 7), # test without a comparison at all + ('int_is_true', 4242, 1, 0), + ('int_is_zero', 4242, 0, 1), + ('float_lt', -0.5, 0.2, -0.5), + ('float_eq', 1.1, 1.1, 1.2), + ]: + called = [] + + ops = ''' + [%s, %s, i3, i4] + i2 = %s(%s) + cond_call(i2, ConstClass(func_ptr), i3, i4) + guard_no_exception(descr=faildescr) [] + finish() + ''' % ("i0" if operation.startswith('int') else "f0", + "i1" if operation.startswith('int') else "f1", + operation, + ("i1" if operation.startswith('int_is_') else + "i0, i1" if operation.startswith('int') else + "f0, f1")) + loop = parse(ops, namespace={'func_ptr': func_ptr, + 'faildescr': BasicFailDescr()}) + looptoken = JitCellToken() + self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken) + frame = self.cpu.execute_token(looptoken, arg1, arg2_if_false, 0, 0) + assert called == [] + frame = self.cpu.execute_token(looptoken, arg1, arg2_if_true, + 67, 89) + assert called == [(67, 89)] + def test_force_operations_returning_void(self): values = [] def maybe_force(token, flag): diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py --- a/rpython/jit/backend/x86/assembler.py +++ b/rpython/jit/backend/x86/assembler.py @@ -114,10 +114,7 @@ def build_frame_realloc_slowpath(self): mc = codebuf.MachineCodeBlockWrapper() self._push_all_regs_to_frame(mc, [], self.cpu.supports_floats) - # this is the gcmap stored by push_gcmap(mov=True) in _check_stack_frame - mc.MOV_rs(ecx.value, WORD) - gcmap_ofs = self.cpu.get_ofs_of_frame_field('jf_gcmap') - mc.MOV_br(gcmap_ofs, ecx.value) + # the caller already did push_gcmap(store=True) if IS_X86_64: mc.MOV_rs(esi.value, WORD*2) @@ -147,7 +144,7 @@ self._load_shadowstack_top_in_ebx(mc, gcrootmap) mc.MOV_mr((ebx.value, -WORD), eax.value) - mc.MOV_bi(gcmap_ofs, 0) + self.pop_gcmap(mc) # cancel the push_gcmap(store=True) in the caller self._pop_all_regs_from_frame(mc, [], self.cpu.supports_floats) mc.RET() self._frame_realloc_slowpath = mc.materialize(self.cpu, []) @@ -164,6 +161,7 @@ # the end of this function. self._push_all_regs_to_frame(mc, cond_call_register_arguments + [eax], supports_floats, callee_only) + # the caller already did push_gcmap(store=True) if IS_X86_64: mc.SUB(esp, imm(WORD)) # alignment self.set_extra_stack_depth(mc, 2 * WORD) @@ -182,8 +180,8 @@ mc.ADD(esp, imm(WORD * 7)) self.set_extra_stack_depth(mc, 0) self._reload_frame_if_necessary(mc, align_stack=True) + self.pop_gcmap(mc) # cancel the push_gcmap(store=True) in the caller self._pop_all_regs_from_frame(mc, [], supports_floats, callee_only) - self.pop_gcmap(mc) # push_gcmap(store=True) done by the caller mc.RET() return mc.materialize(self.cpu, []) @@ -203,10 +201,7 @@ assert kind in ['fixed', 'str', 'unicode', 'var'] mc = codebuf.MachineCodeBlockWrapper() self._push_all_regs_to_frame(mc, [eax, edi], self.cpu.supports_floats) - # store the gc pattern - ofs = self.cpu.get_ofs_of_frame_field('jf_gcmap') - mc.MOV_rs(ecx.value, WORD) - mc.MOV_br(ofs, ecx.value) + # the caller already did push_gcmap(store=True) # if kind == 'fixed': addr = self.cpu.gc_ll_descr.get_malloc_slowpath_addr() @@ -258,8 +253,7 @@ self.set_extra_stack_depth(mc, 0) self._pop_all_regs_from_frame(mc, [eax, edi], self.cpu.supports_floats) mc.MOV(edi, heap(nursery_free_adr)) # load this in EDI - # clear the gc pattern - mc.MOV_bi(ofs, 0) + self.pop_gcmap(mc) # push_gcmap(store=True) done by the caller mc.RET() # # If the slowpath malloc failed, we raise a MemoryError that @@ -646,7 +640,7 @@ jg_location = mc.get_relative_pos() mc.MOV_si(WORD, 0xffffff) # force writing 32 bit ofs2 = mc.get_relative_pos() - 4 - self.push_gcmap(mc, gcmap, mov=True) + self.push_gcmap(mc, gcmap, store=True) mc.CALL(imm(self._frame_realloc_slowpath)) # patch the JG above offset = mc.get_relative_pos() - jg_location @@ -732,8 +726,10 @@ def _assemble(self, regalloc, inputargs, operations): self._regalloc = regalloc + self.last_cc = rx86.cond_none regalloc.compute_hint_frame_locations(operations) regalloc.walk_operations(inputargs, operations) + assert self.last_cc == rx86.cond_none if we_are_translated() or self.cpu.dont_keepalive_stuff: self._regalloc = None # else keep it around for debugging frame_depth = regalloc.get_final_frame_depth() @@ -928,8 +924,8 @@ oopspecindex = effectinfo.oopspecindex genop_math_list[oopspecindex](self, op, arglocs, resloc) - def regalloc_perform_with_guard(self, op, guard_op, faillocs, - arglocs, resloc, frame_depth): + def regalloc_perform_guard(self, guard_op, faillocs, arglocs, resloc, + frame_depth): faildescr = guard_op.getdescr() assert isinstance(faildescr, AbstractFailDescr) failargs = guard_op.getfailargs() @@ -937,21 +933,12 @@ guard_token = self.implement_guard_recovery(guard_opnum, faildescr, failargs, faillocs, frame_depth) - if op is None: - dispatch_opnum = guard_opnum - else: - dispatch_opnum = op.getopnum() - genop_guard_list[dispatch_opnum](self, op, guard_op, guard_token, - arglocs, resloc) + genop_guard_list[guard_opnum](self, guard_op, guard_token, + arglocs, resloc) if not we_are_translated(): # must be added by the genop_guard_list[]() assert guard_token is self.pending_guard_tokens[-1] - def regalloc_perform_guard(self, guard_op, faillocs, arglocs, resloc, - frame_depth): - self.regalloc_perform_with_guard(None, guard_op, faillocs, arglocs, - resloc, frame_depth) - def load_effective_addr(self, sizereg, baseofs, scale, result, frm=imm0): self.mc.LEA(result, addr_add(frm, sizereg, baseofs, scale)) @@ -983,88 +970,70 @@ self.mc.LEA_rm(result_loc.value, (loc.value, delta)) return genop_binary_or_lea + def flush_cc(self, cond, result_loc): + # After emitting a instruction that leaves a boolean result in + # a condition code (cc), call this. In the common case, result_loc + # will be set to ebp by the regalloc, which in this case means + # "propagate it between this operation and the next guard by keeping + # it in the cc". In the uncommon case, result_loc is another + # register, and we emit a load from the cc into this register. + assert self.last_cc == rx86.cond_none + if result_loc is ebp: + self.last_cc = cond + else: + rl = result_loc.lowest8bits() + self.mc.SET_ir(cond, rl.value) + self.mc.MOVZX8_rr(result_loc.value, rl.value) + def _cmpop(cond, rev_cond): + cond = rx86.Conditions[cond] + rev_cond = rx86.Conditions[rev_cond] + # def genop_cmp(self, op, arglocs, result_loc): - rl = result_loc.lowest8bits() if isinstance(op.getarg(0), Const): self.mc.CMP(arglocs[1], arglocs[0]) - self.mc.SET_ir(rx86.Conditions[rev_cond], rl.value) + self.flush_cc(rev_cond, result_loc) else: self.mc.CMP(arglocs[0], arglocs[1]) - self.mc.SET_ir(rx86.Conditions[cond], rl.value) - self.mc.MOVZX8_rr(result_loc.value, rl.value) + self.flush_cc(cond, result_loc) return genop_cmp - def _cmpop_float(cond, rev_cond, is_ne=False): - def genop_cmp(self, op, arglocs, result_loc): - if isinstance(arglocs[0], RegLoc): + def _if_parity_clear_zero_and_carry(self): + self.mc.J_il8(rx86.Conditions['NP'], 0) + jnp_location = self.mc.get_relative_pos() + # CMP EBP, 0: as EBP cannot be null here, that operation should + # always clear zero and carry + self.mc.CMP_ri(ebp.value, 0) + # patch the JNP above + offset = self.mc.get_relative_pos() - jnp_location + assert 0 < offset <= 127 + self.mc.overwrite(jnp_location-1, chr(offset)) + + def _cmpop_float(cond, rev_cond): + is_ne = cond == 'NE' + need_direct_p = 'A' not in cond + need_rev_p = 'A' not in rev_cond + cond_contains_e = ('E' in cond) ^ ('N' in cond) + cond = rx86.Conditions[cond] + rev_cond = rx86.Conditions[rev_cond] + # + def genop_cmp_float(self, op, arglocs, result_loc): + if need_direct_p: + direct_case = not isinstance(arglocs[1], RegLoc) + else: + direct_case = isinstance(arglocs[0], RegLoc) + if direct_case: self.mc.UCOMISD(arglocs[0], arglocs[1]) checkcond = cond + need_p = need_direct_p else: self.mc.UCOMISD(arglocs[1], arglocs[0]) checkcond = rev_cond - - tmp1 = result_loc.lowest8bits() - if IS_X86_32: - tmp2 = result_loc.higher8bits() - elif IS_X86_64: - tmp2 = X86_64_SCRATCH_REG.lowest8bits() - - self.mc.SET_ir(rx86.Conditions[checkcond], tmp1.value) - if is_ne: - self.mc.SET_ir(rx86.Conditions['P'], tmp2.value) - self.mc.OR8_rr(tmp1.value, tmp2.value) - else: - self.mc.SET_ir(rx86.Conditions['NP'], tmp2.value) - self.mc.AND8_rr(tmp1.value, tmp2.value) - self.mc.MOVZX8_rr(result_loc.value, tmp1.value) - return genop_cmp - - def _cmpop_guard(cond, rev_cond, false_cond, false_rev_cond): - def genop_cmp_guard(self, op, guard_op, guard_token, arglocs, result_loc): - guard_opnum = guard_op.getopnum() - if isinstance(op.getarg(0), Const): - self.mc.CMP(arglocs[1], arglocs[0]) - if guard_opnum == rop.GUARD_FALSE: - self.implement_guard(guard_token, rev_cond) - else: - self.implement_guard(guard_token, false_rev_cond) - else: - self.mc.CMP(arglocs[0], arglocs[1]) - if guard_opnum == rop.GUARD_FALSE: - self.implement_guard(guard_token, cond) - else: - self.implement_guard(guard_token, false_cond) - return genop_cmp_guard - - def _cmpop_guard_float(cond, rev_cond, false_cond, false_rev_cond): - need_direct_jp = 'A' not in cond - need_rev_jp = 'A' not in rev_cond - def genop_cmp_guard_float(self, op, guard_op, guard_token, arglocs, - result_loc): - guard_opnum = guard_op.getopnum() - if isinstance(arglocs[0], RegLoc): - self.mc.UCOMISD(arglocs[0], arglocs[1]) - checkcond = cond - checkfalsecond = false_cond - need_jp = need_direct_jp - else: - self.mc.UCOMISD(arglocs[1], arglocs[0]) - checkcond = rev_cond - checkfalsecond = false_rev_cond - need_jp = need_rev_jp - if guard_opnum == rop.GUARD_FALSE: - if need_jp: - self.mc.J_il8(rx86.Conditions['P'], 6) - self.implement_guard(guard_token, checkcond) - else: - if need_jp: - self.mc.J_il8(rx86.Conditions['P'], 2) - self.mc.J_il8(rx86.Conditions[checkcond], 5) - self.implement_guard(guard_token) - else: - self.implement_guard(guard_token, checkfalsecond) - return genop_cmp_guard_float + need_p = need_rev_p + if need_p: + self._if_parity_clear_zero_and_carry() + self.flush_cc(checkcond, result_loc) + return genop_cmp_float def simple_call(self, fnloc, arglocs, result_loc=eax): if result_loc is xmm0: @@ -1127,37 +1096,17 @@ genop_ptr_eq = genop_instance_ptr_eq = genop_int_eq genop_ptr_ne = genop_instance_ptr_ne = genop_int_ne - genop_float_lt = _cmpop_float('B', 'A') - genop_float_le = _cmpop_float('BE', 'AE') - genop_float_ne = _cmpop_float('NE', 'NE', is_ne=True) - genop_float_eq = _cmpop_float('E', 'E') - genop_float_gt = _cmpop_float('A', 'B') - genop_float_ge = _cmpop_float('AE', 'BE') - genop_uint_gt = _cmpop("A", "B") genop_uint_lt = _cmpop("B", "A") genop_uint_le = _cmpop("BE", "AE") genop_uint_ge = _cmpop("AE", "BE") - genop_guard_int_lt = _cmpop_guard("L", "G", "GE", "LE") - genop_guard_int_le = _cmpop_guard("LE", "GE", "G", "L") - genop_guard_int_eq = _cmpop_guard("E", "E", "NE", "NE") - genop_guard_int_ne = _cmpop_guard("NE", "NE", "E", "E") - genop_guard_int_gt = _cmpop_guard("G", "L", "LE", "GE") - genop_guard_int_ge = _cmpop_guard("GE", "LE", "L", "G") - genop_guard_ptr_eq = genop_guard_instance_ptr_eq = genop_guard_int_eq - genop_guard_ptr_ne = genop_guard_instance_ptr_ne = genop_guard_int_ne - - genop_guard_uint_gt = _cmpop_guard("A", "B", "BE", "AE") - genop_guard_uint_lt = _cmpop_guard("B", "A", "AE", "BE") - genop_guard_uint_le = _cmpop_guard("BE", "AE", "A", "B") - genop_guard_uint_ge = _cmpop_guard("AE", "BE", "B", "A") - - genop_guard_float_lt = _cmpop_guard_float("B", "A", "AE","BE") - genop_guard_float_le = _cmpop_guard_float("BE","AE", "A", "B") - genop_guard_float_eq = _cmpop_guard_float("E", "E", "NE","NE") - genop_guard_float_gt = _cmpop_guard_float("A", "B", "BE","AE") - genop_guard_float_ge = _cmpop_guard_float("AE","BE", "B", "A") + genop_float_lt = _cmpop_float("B", "A") + genop_float_le = _cmpop_float("BE","AE") + genop_float_eq = _cmpop_float("E", "E") + genop_float_ne = _cmpop_float("NE", "NE") + genop_float_gt = _cmpop_float("A", "B") + genop_float_ge = _cmpop_float("AE","BE") def genop_math_sqrt(self, op, arglocs, resloc): self.mc.SQRTSD(arglocs[0], resloc) @@ -1187,20 +1136,6 @@ else: raise AssertionError("bad number of bytes") - def genop_guard_float_ne(self, op, guard_op, guard_token, arglocs, result_loc): - guard_opnum = guard_op.getopnum() - if isinstance(arglocs[0], RegLoc): - self.mc.UCOMISD(arglocs[0], arglocs[1]) - else: - self.mc.UCOMISD(arglocs[1], arglocs[0]) - if guard_opnum == rop.GUARD_TRUE: - self.mc.J_il8(rx86.Conditions['P'], 6) - self.implement_guard(guard_token, 'E') - else: - self.mc.J_il8(rx86.Conditions['P'], 2) - self.mc.J_il8(rx86.Conditions['E'], 5) - self.implement_guard(guard_token) - def genop_float_neg(self, op, arglocs, resloc): # Following what gcc does: res = x ^ 0x8000000000000000 self.mc.XORPD(arglocs[0], heap(self.float_const_neg_addr)) @@ -1247,33 +1182,20 @@ else: self.mov(loc0, resloc) - def genop_guard_int_is_true(self, op, guard_op, guard_token, arglocs, resloc): - guard_opnum = guard_op.getopnum() - self.mc.CMP(arglocs[0], imm0) - if guard_opnum == rop.GUARD_TRUE: - self.implement_guard(guard_token, 'Z') + def test_location(self, loc): + assert not isinstance(loc, ImmedLoc) + if isinstance(loc, RegLoc): + self.mc.TEST_rr(loc.value, loc.value) # more compact else: - self.implement_guard(guard_token, 'NZ') + self.mc.CMP(loc, imm0) # works from memory too def genop_int_is_true(self, op, arglocs, resloc): - self.mc.CMP(arglocs[0], imm0) - rl = resloc.lowest8bits() - self.mc.SET_ir(rx86.Conditions['NE'], rl.value) - self.mc.MOVZX8(resloc, rl) - - def genop_guard_int_is_zero(self, op, guard_op, guard_token, arglocs, resloc): - guard_opnum = guard_op.getopnum() - self.mc.CMP(arglocs[0], imm0) - if guard_opnum == rop.GUARD_TRUE: - self.implement_guard(guard_token, 'NZ') - else: - self.implement_guard(guard_token, 'Z') + self.test_location(arglocs[0]) + self.flush_cc(rx86.Conditions['NZ'], resloc) _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit