Author: Richard Plangger <[email protected]>
Branch: vecopt-merge
Changeset: r79581:3cf43a0720f1
Date: 2015-09-10 10:51 +0200
http://bitbucket.org/pypy/pypy/changeset/3cf43a0720f1/
Log: merged default
diff too long, truncating to 2000 out of 12637 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
@@ -429,7 +430,7 @@
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
diff --git a/lib-python/conftest.py b/lib-python/conftest.py
--- a/lib-python/conftest.py
+++ b/lib-python/conftest.py
@@ -303,7 +303,7 @@
RegrTest('test_memoryio.py'),
RegrTest('test_memoryview.py'),
RegrTest('test_md5.py'),
- RegrTest('test_mhlib.py'),
+ RegrTest('test_mhlib.py', usemodules='binascii struct'),
RegrTest('test_mimetools.py'),
RegrTest('test_mimetypes.py'),
RegrTest('test_MimeWriter.py', core=False, usemodules='binascii'),
diff --git a/lib_pypy/_curses.py b/lib_pypy/_curses.py
--- a/lib_pypy/_curses.py
+++ b/lib_pypy/_curses.py
@@ -1026,16 +1026,22 @@
def tigetflag(capname):
_ensure_initialised_setupterm()
+ if isinstance(capname, unicode):
+ capname = capname.encode('ascii')
return lib.tigetflag(capname)
def tigetnum(capname):
_ensure_initialised_setupterm()
+ if isinstance(capname, unicode):
+ capname = capname.encode('ascii')
return lib.tigetnum(capname)
def tigetstr(capname):
_ensure_initialised_setupterm()
+ if isinstance(capname, unicode):
+ capname = capname.encode('ascii')
val = lib.tigetstr(capname)
if int(ffi.cast("intptr_t", val)) in (0, -1):
return None
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.1
+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.1"
-__version_info__ = (1, 2, 1)
+__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
@@ -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
@@ -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
@@ -468,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(' ', '_'))
@@ -522,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:
@@ -1107,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/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/embedding.rst b/pypy/doc/embedding.rst
--- a/pypy/doc/embedding.rst
+++ b/pypy/doc/embedding.rst
@@ -20,10 +20,6 @@
It initializes the RPython/PyPy GC and does a bunch of necessary startup
code. This function cannot fail.
-.. function:: void pypy_init_threads(void);
-
- Initialize threads. Only need to be called if there are any threads involved
-
.. function:: int pypy_setup_home(char* home, int verbose);
This function searches the PyPy standard library starting from the given
@@ -38,6 +34,11 @@
Function returns 0 on success or -1 on failure, can be called multiple times
until the library is found.
+.. function:: void pypy_init_threads(void);
+
+ Initialize threads. Only need to be called if there are any threads
involved.
+ *Must be called after pypy_setup_home()*
+
.. function:: int pypy_execute_source(char* source);
Execute the Python source code given in the ``source`` argument. In case of
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-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -5,6 +5,23 @@
.. this is a revision shortly after release-2.6.1
.. startrev: 07769be4057b
+.. branch: keys_with_hash
+Improve the performance of dict.update() and a bunch of methods from
+sets, by reusing the hash value stored in one dict when inspecting
+or changing another dict with that key.
+
+.. branch: optresult-unroll
+A major refactoring of the ResOperations that kills Box. Also rewrote
+unrolling to enable future enhancements. Should improve warmup time
+by 20% or so.
+
+.. branch: optimize-cond-call
+Optimize common sequences of operations like
+``int_lt/cond_call`` in the JIT backends
+
+.. branch: missing_openssl_include
+Fix for missing headers in OpenBSD, already applied in downstream ports
+
.. branch: vecopt
.. branch: vecopt-merge
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/__pypy__/__init__.py b/pypy/module/__pypy__/__init__.py
--- a/pypy/module/__pypy__/__init__.py
+++ b/pypy/module/__pypy__/__init__.py
@@ -111,22 +111,17 @@
'interp_magic.mapdict_cache_counter')
PYC_MAGIC = get_pyc_magic(self.space)
self.extra_interpdef('PYC_MAGIC', 'space.wrap(%d)' % PYC_MAGIC)
- # XXX
- # the following code prevents --fork-before=pyjitpl from working,
- # proper fix would be to use some llop that is only rendered by the
- # JIT
- #
- #try:
- # from rpython.jit.backend import detect_cpu
- # model = detect_cpu.autodetect()
- # self.extra_interpdef('cpumodel', 'space.wrap(%r)' % model)
- #except Exception:
- # if self.space.config.translation.jit:
- # raise
- # else:
- # pass # ok fine to ignore in this case
- #
- #if self.space.config.translation.jit:
- ## features = detect_cpu.getcpufeatures(model)
- # self.extra_interpdef('jit_backend_features',
- # 'space.wrap(%r)' % features)
+ try:
+ from rpython.jit.backend import detect_cpu
+ model = detect_cpu.autodetect()
+ self.extra_interpdef('cpumodel', 'space.wrap(%r)' % model)
+ except Exception:
+ if self.space.config.translation.jit:
+ raise
+ else:
+ pass # ok fine to ignore in this case
+
+ if self.space.config.translation.jit:
+ features = detect_cpu.getcpufeatures(model)
+ self.extra_interpdef('jit_backend_features',
+ 'space.wrap(%r)' % features)
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.1"
+VERSION = "1.3.0"
class Module(MixedModule):
diff --git a/pypy/module/_cffi_backend/ccallback.py
b/pypy/module/_cffi_backend/ccallback.py
--- a/pypy/module/_cffi_backend/ccallback.py
+++ b/pypy/module/_cffi_backend/ccallback.py
@@ -19,13 +19,27 @@
# ____________________________________________________________
+class Closure(object):
+ """This small class is here to have a __del__ outside any cycle."""
+
+ ll_error = lltype.nullptr(rffi.CCHARP.TO) # set manually
+
+ def __init__(self, ptr):
+ self.ptr = ptr
+
+ def __del__(self):
+ clibffi.closureHeap.free(rffi.cast(clibffi.FFI_CLOSUREP, self.ptr))
+ if self.ll_error:
+ lltype.free(self.ll_error, flavor='raw')
+
+
class W_CDataCallback(W_CData):
#_immutable_fields_ = ...
- ll_error = lltype.nullptr(rffi.CCHARP.TO)
w_onerror = None
def __init__(self, space, ctype, w_callable, w_error, w_onerror):
raw_closure = rffi.cast(rffi.CCHARP, clibffi.closureHeap.alloc())
+ self._closure = Closure(raw_closure)
W_CData.__init__(self, space, raw_closure, ctype)
#
if not space.is_true(space.callable(w_callable)):
@@ -44,10 +58,11 @@
if size > 0:
if fresult.is_primitive_integer and size < SIZE_OF_FFI_ARG:
size = SIZE_OF_FFI_ARG
- self.ll_error = lltype.malloc(rffi.CCHARP.TO, size, flavor='raw',
- zero=True)
+ self._closure.ll_error = lltype.malloc(rffi.CCHARP.TO, size,
+ flavor='raw', zero=True)
if not space.is_none(w_error):
- convert_from_object_fficallback(fresult, self.ll_error, w_error)
+ convert_from_object_fficallback(fresult, self._closure.ll_error,
+ w_error)
#
self.unique_id = compute_unique_id(self)
global_callback_mapping.set(self.unique_id, self)
@@ -74,12 +89,6 @@
from pypy.module.thread.os_thread import setup_threads
setup_threads(space)
- #@rgc.must_be_light_finalizer
- def __del__(self):
- clibffi.closureHeap.free(rffi.cast(clibffi.FFI_CLOSUREP, self._ptr))
- if self.ll_error:
- lltype.free(self.ll_error, flavor='raw')
-
def _repr_extra(self):
space = self.space
return 'calling ' + space.str_w(space.repr(self.w_callable))
@@ -114,8 +123,8 @@
def write_error_return_value(self, ll_res):
fresult = self.getfunctype().ctitem
if fresult.size > 0:
- misc._raw_memcopy(self.ll_error, ll_res, fresult.size)
- keepalive_until_here(self) # to keep self.ll_error alive
+ misc._raw_memcopy(self._closure.ll_error, ll_res, fresult.size)
+ keepalive_until_here(self) # to keep self._closure.ll_error alive
global_callback_mapping = rweakref.RWeakValueDictionary(int, W_CDataCallback)
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.1"
diff --git a/pypy/module/pypyjit/test_pypy_c/model.py
b/pypy/module/pypyjit/test_pypy_c/model.py
--- a/pypy/module/pypyjit/test_pypy_c/model.py
+++ b/pypy/module/pypyjit/test_pypy_c/model.py
@@ -326,7 +326,7 @@
# to repeat it every time
ticker_check = """
guard_not_invalidated?
- ticker0 = getfield_raw(#, descr=<FieldS
pypysig_long_struct.c_value .*>)
+ ticker0 = getfield_raw_i(#, descr=<FieldS
pypysig_long_struct.c_value .*>)
ticker_cond0 = int_lt(ticker0, 0)
guard_false(ticker_cond0, descr=...)
"""
@@ -335,7 +335,7 @@
# this is the ticker check generated if we have threads
thread_ticker_check = """
guard_not_invalidated?
- ticker0 = getfield_raw(#, descr=<FieldS
pypysig_long_struct.c_value .*>)
+ ticker0 = getfield_raw_i(#, descr=<FieldS
pypysig_long_struct.c_value .*>)
ticker1 = int_sub(ticker0, #)
setfield_raw(#, ticker1, descr=<FieldS pypysig_long_struct.c_value
.*>)
ticker_cond0 = int_lt(ticker1, 0)
@@ -345,7 +345,7 @@
#
# this is the ticker check generated in PyFrame.handle_operation_error
exc_ticker_check = """
- ticker2 = getfield_raw(#, descr=<FieldS
pypysig_long_struct.c_value .*>)
+ ticker2 = getfield_raw_i(#, descr=<FieldS
pypysig_long_struct.c_value .*>)
ticker_cond1 = int_lt(ticker2, 0)
guard_false(ticker_cond1, descr=...)
"""
diff --git a/pypy/module/pypyjit/test_pypy_c/test_00_model.py
b/pypy/module/pypyjit/test_pypy_c/test_00_model.py
--- a/pypy/module/pypyjit/test_pypy_c/test_00_model.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_00_model.py
@@ -76,7 +76,7 @@
stdout = stdout.splitlines(True)[-1]
#
# parse the JIT log
- rawlog = logparser.parse_log_file(str(logfile))
+ rawlog = logparser.parse_log_file(str(logfile), verbose=False)
rawtraces = logparser.extract_category(rawlog, 'jit-log-opt-')
log = Log(rawtraces)
log.result = eval(stdout)
@@ -471,7 +471,7 @@
# this is the actual loop
'int_lt', 'guard_true', 'int_add',
# this is the signal checking stuff
- 'guard_not_invalidated', 'getfield_raw', 'int_lt', 'guard_false',
+ 'guard_not_invalidated', 'getfield_raw_i', 'int_lt', 'guard_false',
'jump'
]
@@ -536,7 +536,7 @@
# this is the actual loop
'int_lt', 'guard_true', 'force_token', 'int_add',
# this is the signal checking stuff
- 'guard_not_invalidated', 'getfield_raw', 'int_lt', 'guard_false',
+ 'guard_not_invalidated', 'getfield_raw_i', 'int_lt', 'guard_false',
'jump'
]
@@ -555,7 +555,7 @@
i8 = int_add(i4, 1)
# signal checking stuff
guard_not_invalidated(descr=...)
- i10 = getfield_raw(..., descr=<.* pypysig_long_struct.c_value .*>)
+ i10 = getfield_raw_i(..., descr=<.* pypysig_long_struct.c_value
.*>)
i14 = int_lt(i10, 0)
guard_false(i14, descr=...)
jump(..., descr=...)
@@ -609,13 +609,13 @@
log = self.run(f, import_site=True)
loop, = log.loops_by_id('ntohs')
assert loop.match_by_id('ntohs', """
- p12 = call(ConstClass(ntohs), 1, descr=...)
+ i12 = call_i(ConstClass(ntohs), 1, descr=...)
guard_no_exception(descr=...)
""",
include_guard_not_invalidated=False)
#
py.test.raises(InvalidMatch, loop.match_by_id, 'ntohs', """
guard_not_invalidated(descr=...)
- p12 = call(ConstClass(foobar), 1, descr=...)
+ i12 = call_i(ConstClass(foobar), 1, descr=...)
guard_no_exception(descr=...)
""")
diff --git a/pypy/module/pypyjit/test_pypy_c/test_array.py
b/pypy/module/pypyjit/test_pypy_c/test_array.py
--- a/pypy/module/pypyjit/test_pypy_c/test_array.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_array.py
@@ -42,7 +42,7 @@
guard_not_invalidated?
i13 = int_lt(i7, i9)
guard_true(i13, descr=...)
- i15 = getarrayitem_raw(i10, i7, descr=<ArrayS .>)
+ i15 = getarrayitem_raw_i(i10, i7, descr=<ArrayS .>)
i16 = int_add_ovf(i8, i15)
guard_no_overflow(descr=...)
i18 = int_add(i7, 1)
@@ -74,12 +74,12 @@
guard_true(i13, descr=...)
guard_not_invalidated(descr=...)
# the bound check guard on img has been killed (thanks to the
asserts)
- i14 = getarrayitem_raw(i10, i8, descr=<ArrayS .>)
+ i14 = getarrayitem_raw_i(i10, i8, descr=<ArrayS .>)
i15 = int_add_ovf(i9, i14)
guard_no_overflow(descr=...)
i17 = int_sub(i8, 640)
# the bound check guard on intimg has been killed (thanks to the
asserts)
- i18 = getarrayitem_raw(i11, i17, descr=<ArrayS .>)
+ i18 = getarrayitem_raw_i(i11, i17, descr=<ArrayS .>)
i19 = int_add_ovf(i18, i15)
guard_no_overflow(descr=...)
setarrayitem_raw(i11, i8, _, descr=<ArrayS .>)
@@ -93,7 +93,7 @@
guard_true(i13, descr=...)
guard_not_invalidated(descr=...)
# the bound check guard on img has been killed (thanks to the
asserts)
- i14 = getarrayitem_raw(i10, i8, descr=<ArrayS .>)
+ i14 = getarrayitem_raw_i(i10, i8, descr=<ArrayS .>)
# advanced: the following int_add cannot overflow, because:
# - i14 fits inside 32 bits
# - i9 fits inside 33 bits, because:
@@ -107,7 +107,7 @@
i15 = int_add(i9, i14)
i17 = int_sub(i8, 640)
# the bound check guard on intimg has been killed (thanks to the
asserts)
- i18 = getarrayitem_raw(i11, i17, descr=<ArrayS .>)
+ i18 = getarrayitem_raw_i(i11, i17, descr=<ArrayS .>)
i19 = int_add(i18, i15)
# guard checking that i19 actually fits into 32bit
i20 = int_signext(i19, 4)
@@ -139,10 +139,10 @@
guard_true(i10, descr=...)
i11 = int_lt(i6, i7)
guard_true(i11, descr=...)
- f13 = getarrayitem_raw(i8, i6, descr=<ArrayF 8>)
+ f13 = getarrayitem_raw_f(i8, i6, descr=<ArrayF 8>)
f15 = float_add(f13, 20.500000)
setarrayitem_raw(i8, i6, f15, descr=<ArrayF 8>)
- f16 = getarrayitem_raw(i8, i6, descr=<ArrayF 8>)
+ f16 = getarrayitem_raw_f(i8, i6, descr=<ArrayF 8>)
i18 = float_eq(f16, 42.000000)
guard_true(i18, descr=...)
i20 = int_add(i6, 1)
@@ -175,12 +175,12 @@
guard_true(i10, descr=...)
i11 = int_lt(i6, i7)
guard_true(i11, descr=...)
- i13 = getarrayitem_raw(i8, i6, descr=<Array. 4>)
+ i13 = getarrayitem_raw_i(i8, i6, descr=<Array. 4>)
f14 = cast_singlefloat_to_float(i13)
f16 = float_add(f14, 20.500000)
i17 = cast_float_to_singlefloat(f16)
setarrayitem_raw(i8, i6,i17, descr=<Array. 4>)
- i18 = getarrayitem_raw(i8, i6, descr=<Array. 4>)
+ i18 = getarrayitem_raw_i(i8, i6, descr=<Array. 4>)
f19 = cast_singlefloat_to_float(i18)
i21 = float_eq(f19, 42.000000)
guard_true(i21, descr=...)
@@ -225,23 +225,23 @@
...
i20 = int_ge(i18, i8)
guard_false(i20, descr=...)
- f21 = getarrayitem_raw(i13, i18, descr=...)
+ f21 = getarrayitem_raw_f(i13, i18, descr=...)
i14 = int_sub(i6, 1)
i15 = int_ge(i14, i8)
guard_false(i15, descr=...)
- f23 = getarrayitem_raw(i13, i14, descr=...)
+ f23 = getarrayitem_raw_f(i13, i14, descr=...)
f24 = float_add(f21, f23)
- f26 = getarrayitem_raw(i13, i6, descr=...)
+ f26 = getarrayitem_raw_f(i13, i6, descr=...)
f27 = float_add(f24, f26)
i29 = int_add(i6, 1)
i31 = int_ge(i29, i8)
guard_false(i31, descr=...)
- f33 = getarrayitem_raw(i13, i29, descr=...)
+ f33 = getarrayitem_raw_f(i13, i29, descr=...)
f34 = float_add(f27, f33)
i36 = int_add(i6, 2)
i38 = int_ge(i36, i8)
guard_false(i38, descr=...)
- f39 = getarrayitem_raw(i13, i36, descr=...)
+ f39 = getarrayitem_raw_f(i13, i36, descr=...)
...
""")
@@ -276,20 +276,20 @@
expected_src="""
...
i17 = int_and(i14, 255)
- f18 = getarrayitem_raw(i8, i17, descr=...)
+ f18 = getarrayitem_raw_f(i8, i17, descr=...)
i19s = int_sub_ovf(i6, 1)
guard_no_overflow(descr=...)
i22s = int_and(i19s, 255)
- f20 = getarrayitem_raw(i8, i22s, descr=...)
+ f20 = getarrayitem_raw_f(i8, i22s, descr=...)
f21 = float_add(f18, f20)
- f23 = getarrayitem_raw(i8, i10, descr=...)
+ f23 = getarrayitem_raw_f(i8, i10, descr=...)
f24 = float_add(f21, f23)
i26 = int_add(i6, 1)
i29 = int_and(i26, 255)
- f30 = getarrayitem_raw(i8, i29, descr=...)
+ f30 = getarrayitem_raw_f(i8, i29, descr=...)
f31 = float_add(f24, f30)
i33 = int_add(i6, 2)
i36 = int_and(i33, 255)
- f37 = getarrayitem_raw(i8, i36, descr=...)
+ f37 = getarrayitem_raw_f(i8, i36, descr=...)
...
""")
diff --git a/pypy/module/pypyjit/test_pypy_c/test_buffers.py
b/pypy/module/pypyjit/test_pypy_c/test_buffers.py
--- a/pypy/module/pypyjit/test_pypy_c/test_buffers.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_buffers.py
@@ -18,7 +18,7 @@
loop, = log.loops_by_filename(self.filepath)
assert loop.match_by_id('match', """
guard_not_invalidated(descr=...)
- i65 = getfield_gc(p18, descr=...)
+ i65 = getfield_gc_i(p18, descr=...)
i67 = int_gt(0, i65)
guard_false(i67, descr=...)
i69 = int_gt(#, i65)
@@ -42,7 +42,7 @@
assert loop.match_by_id('unpack', """
guard_not_invalidated(descr=...)
p90 = newstr(4)
- call(ConstClass(copy_raw_to_string), i55, p90, 0, 4, descr=<Callv
0 irii EF=5>)
+ call_n(ConstClass(copy_raw_to_string), i55, p90, 0, 4,
descr=<Callv 0 irii EF=5>)
guard_no_exception(descr=...)
i91 = strgetitem(p90, 0)
i92 = strgetitem(p90, 1)
@@ -56,7 +56,7 @@
guard_false(i99, descr=...)
i100 = int_lshift(i98, 24)
i101 = int_or(i97, i100)
- i102 = getfield_raw(#, descr=<FieldS pypysig_long_struct.c_value
0>)
+ i102 = getfield_raw_i(#, descr=<FieldS pypysig_long_struct.c_value
0>)
i103 = int_lt(i102, 0)
guard_false(i103, descr=...)
""")
diff --git a/pypy/module/pypyjit/test_pypy_c/test_call.py
b/pypy/module/pypyjit/test_pypy_c/test_call.py
--- a/pypy/module/pypyjit/test_pypy_c/test_call.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_call.py
@@ -31,7 +31,7 @@
functrace, loop = log.loops_by_filename(self.filepath)
assert loop.match_by_id('call_rec', """
...
- p53 = call_assembler(..., descr=...)
+ p53 = call_assembler_r(..., descr=...)
guard_not_forced(descr=...)
keepalive(...)
guard_no_exception(descr=...)
@@ -73,7 +73,7 @@
ops = entry_bridge.ops_by_id('cond', opcode='LOAD_GLOBAL')
assert log.opnames(ops) == ["guard_value",
"guard_value",
- "getfield_gc", "guard_value",
+ "getfield_gc_r", "guard_value",
"guard_not_invalidated"]
ops = entry_bridge.ops_by_id('add', opcode='LOAD_GLOBAL')
assert log.opnames(ops) == []
@@ -82,12 +82,12 @@
assert log.opnames(ops) == []
#
assert entry_bridge.match_by_id('call', """
- p38 =
call(ConstClass(_ll_1_threadlocalref_get__Ptr_GcStruct_objectLlT_Signed), #,
descr=<Callr . i EF=1 OS=5>)
- p39 = getfield_gc(p38, descr=<FieldP
pypy.interpreter.executioncontext.ExecutionContext.inst_topframeref .*>)
+ p38 =
call_r(ConstClass(_ll_1_threadlocalref_get__Ptr_GcStruct_objectLlT_Signed), #,
descr=<Callr . i EF=1 OS=5>)
+ p39 = getfield_gc_r(p38, descr=<FieldP
pypy.interpreter.executioncontext.ExecutionContext.inst_topframeref .*>)
i40 = force_token()
- p41 = getfield_gc_pure(p38, descr=<FieldP
pypy.interpreter.executioncontext.ExecutionContext.inst_w_tracefunc .*>)
+ p41 = getfield_gc_pure_r(p38, descr=<FieldP
pypy.interpreter.executioncontext.ExecutionContext.inst_w_tracefunc .*>)
guard_value(p41, ConstPtr(ptr42), descr=...)
- i42 = getfield_gc_pure(p38, descr=<FieldU
pypy.interpreter.executioncontext.ExecutionContext.inst_profilefunc .*>)
+ i42 = getfield_gc_pure_i(p38, descr=<FieldU
pypy.interpreter.executioncontext.ExecutionContext.inst_profilefunc .*>)
i43 = int_is_zero(i42)
guard_true(i43, descr=...)
i50 = force_token()
@@ -130,7 +130,8 @@
# -------------------------------
entry_bridge, = log.loops_by_filename(self.filepath,
is_entry_bridge=True)
ops = entry_bridge.ops_by_id('meth1', opcode='LOOKUP_METHOD')
- assert log.opnames(ops) == ['guard_value', 'getfield_gc',
'guard_value',
+ assert log.opnames(ops) == ['guard_value', 'getfield_gc_r',
+ 'guard_value',
'guard_not_invalidated']
# the second LOOKUP_METHOD is folded away
assert list(entry_bridge.ops_by_id('meth2', opcode='LOOKUP_METHOD'))
== []
@@ -349,15 +350,13 @@
# the int strategy is used here
assert loop.match_by_id('append', """
guard_not_invalidated?
- i13 = getfield_gc(p8, descr=<FieldS list.length .*>)
i15 = int_add(i13, 1)
- p15 = getfield_gc(p8, descr=<FieldP list.items .*>)
i17 = arraylen_gc(p15, descr=<ArrayS .>)
i18 = int_lt(i17, i15)
# a cond call to _ll_list_resize_hint_really_look_inside_iff
cond_call(i18, _, p8, i15, 1, descr=<Callv 0 rii EF=5>)
guard_no_exception(descr=...)
- p17 = getfield_gc(p8, descr=<FieldP list.items .*>)
+ p17 = getfield_gc_r(p8, descr=<FieldP list.items .*>)
setarrayitem_gc(p17, i13, i12, descr=<ArrayS .>)
""")
@@ -381,9 +380,9 @@
# make sure that the "block" is not allocated
...
p20 = force_token()
- p22 = new_with_vtable(...)
+ p22 = new_with_vtable(descr=<SizeDescr .*>)
p24 = new_array_clear(1, descr=<ArrayP .>)
- p26 = new_with_vtable(ConstClass(W_ListObject))
+ p26 = new_with_vtable(descr=<SizeDescr .*>)
{{{
setfield_gc(p0, p20, descr=<FieldP .*PyFrame.vable_token .*>)
setfield_gc(p22, ConstPtr(null), descr=<FieldP
pypy.interpreter.argument.Arguments.inst_keywords_w .*>)
@@ -395,7 +394,7 @@
setarrayitem_gc(p24, 0, p26, descr=<ArrayP .>)
setfield_gc(p22, p24, descr=<FieldP .*Arguments.inst_arguments_w
.*>)
}}}
- p32 = call_may_force(_, p18, p22, descr=<Callr . rr EF=7>)
+ p32 = call_may_force_r(_, p18, p22, descr=<Callr . rr EF=7>)
...
""")
@@ -436,24 +435,24 @@
guard_isnull(p5, descr=...)
guard_nonnull_class(p12, ConstClass(W_IntObject), descr=...)
guard_value(p2, ConstPtr(ptr21), descr=...)
- i22 = getfield_gc_pure(p12, descr=<FieldS
pypy.objspace.std.intobject.W_IntObject.inst_intval .*>)
+ i22 = getfield_gc_pure_i(p12, descr=<FieldS
pypy.objspace.std.intobject.W_IntObject.inst_intval .*>)
i24 = int_lt(i22, 5000)
guard_true(i24, descr=...)
guard_value(p7, ConstPtr(ptr25), descr=...)
- p26 = getfield_gc(p7, descr=<FieldP
pypy.objspace.std.dictmultiobject.W_DictMultiObject.inst_strategy .*>)
+ p26 = getfield_gc_r(p7, descr=<FieldP
pypy.objspace.std.dictmultiobject.W_DictMultiObject.inst_strategy .*>)
guard_value(p26, ConstPtr(ptr27), descr=...)
guard_not_invalidated(descr=...)
- p29 =
call(ConstClass(_ll_1_threadlocalref_get__Ptr_GcStruct_objectLlT_Signed), #,
descr=<Callr . i EF=1 OS=5>)
- p30 = getfield_gc(p29, descr=<FieldP
pypy.interpreter.executioncontext.ExecutionContext.inst_topframeref .*>)
+ p29 =
call_r(ConstClass(_ll_1_threadlocalref_get__Ptr_GcStruct_objectLlT_Signed), #,
descr=<Callr . i EF=1 OS=5>)
+ p30 = getfield_gc_r(p29, descr=<FieldP
pypy.interpreter.executioncontext.ExecutionContext.inst_topframeref .*>)
p31 = force_token()
- p32 = getfield_gc_pure(p29, descr=<FieldP
pypy.interpreter.executioncontext.ExecutionContext.inst_w_tracefunc .*>)
+ p32 = getfield_gc_pure_r(p29, descr=<FieldP
pypy.interpreter.executioncontext.ExecutionContext.inst_w_tracefunc .*>)
guard_value(p32, ConstPtr(ptr33), descr=...)
- i34 = getfield_gc_pure(p29, descr=<FieldU
pypy.interpreter.executioncontext.ExecutionContext.inst_profilefunc .*>)
+ i34 = getfield_gc_pure_i(p29, descr=<FieldU
pypy.interpreter.executioncontext.ExecutionContext.inst_profilefunc .*>)
i35 = int_is_zero(i34)
guard_true(i35, descr=...)
- p37 = getfield_gc(ConstPtr(ptr36), descr=<FieldP
pypy.interpreter.nestedscope.Cell.inst_w_value .*>)
+ p37 = getfield_gc_r(ConstPtr(ptr36), descr=<FieldP
pypy.interpreter.nestedscope.Cell.inst_w_value .*>)
guard_nonnull_class(p37, ConstClass(W_IntObject), descr=...)
- i39 = getfield_gc_pure(p37, descr=<FieldS
pypy.objspace.std.intobject.W_IntObject.inst_intval .*>)
+ i39 = getfield_gc_pure_i(p37, descr=<FieldS
pypy.objspace.std.intobject.W_IntObject.inst_intval .*>)
i40 = int_add_ovf(i22, i39)
guard_no_overflow(descr=...)
--TICK--
@@ -470,13 +469,13 @@
""", [])
loop, = log.loops_by_id('call')
assert loop.match("""
- i8 = getfield_gc_pure(p6, descr=<FieldS
pypy.objspace.std.intobject.W_IntObject.inst_intval .*>)
+ i8 = getfield_gc_pure_i(p6, descr=<FieldS
pypy.objspace.std.intobject.W_IntObject.inst_intval .*>)
i10 = int_lt(i8, 5000)
guard_true(i10, descr=...)
i11 = force_token()
i13 = int_add(i8, 1)
--TICK--
- p22 = new_with_vtable(ConstClass(W_IntObject))
+ p22 = new_with_vtable(descr=<SizeDescr .*>)
setfield_gc(p22, i13, descr=<FieldS
pypy.objspace.std.intobject.W_IntObject.inst_intval .*>)
setfield_gc(p4, p22, descr=<FieldP
pypy.interpreter.nestedscope.Cell.inst_w_value .*>)
jump(..., descr=...)
@@ -576,8 +575,8 @@
allops = loop.allops()
calls = [op for op in allops if op.name.startswith('call')]
assert OpMatcher(calls).match('''
- p93 = call(ConstClass(view_as_kwargs), p35, p12, descr=<.*>)
- i103 = call(ConstClass(_match_keywords), ConstPtr(ptr52), 0, 0, p94,
p98, 0, descr=<.*>)
+ p93 = call_r(ConstClass(view_as_kwargs), p35, p12, descr=<.*>)
+ i103 = call_i(ConstClass(_match_keywords), ConstPtr(ptr52), 0, 0, p94,
p98, 0, descr=<.*>)
''')
assert len([op for op in allops if op.name.startswith('new')]) == 1
# 1 alloc
diff --git a/pypy/module/pypyjit/test_pypy_c/test_ffi.py
b/pypy/module/pypyjit/test_pypy_c/test_ffi.py
--- a/pypy/module/pypyjit/test_pypy_c/test_ffi.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_ffi.py
@@ -163,7 +163,7 @@
loop, = log.loops_by_filename(self.filepath)
assert loop.match_by_id('getfield', """
guard_not_invalidated(descr=...)
- i57 = getfield_raw(i46, descr=<FieldS dynamic 0>)
+ i57 = getfield_raw_i(i46, descr=<FieldS dynamic 0>)
""")
assert loop.match_by_id('setfield', """
setfield_raw(i44, i57, descr=<FieldS dynamic 0>)
@@ -202,7 +202,7 @@
assert loop.match_by_id('cfficall', """
p96 = force_token()
setfield_gc(p0, p96, descr=<FieldP
pypy.interpreter.pyframe.PyFrame.vable_token .>)
- f97 = call_release_gil(91, i59, 1.0, 3, descr=<Callf 8 fi EF=7
OS=62>)
+ f97 = call_release_gil_f(91, i59, 1.0, 3, descr=<Callf 8 fi EF=7
OS=62>)
guard_not_forced(descr=...)
guard_no_exception(descr=...)
""", ignore_ops=['guard_not_invalidated'])
@@ -244,7 +244,7 @@
assert loop.match_by_id('cfficall', """
p96 = force_token()
setfield_gc(p0, p96, descr=<FieldP
pypy.interpreter.pyframe.PyFrame.vable_token .>)
- i97 = call_release_gil(91, i59, i50, descr=<Calli 4 i EF=7 OS=62>)
+ i97 = call_release_gil_i(91, i59, i50, descr=<Calli 4 i EF=7
OS=62>)
guard_not_forced(descr=...)
guard_no_exception(descr=...)
%s
@@ -288,10 +288,10 @@
assert loop.match_by_id('cfficall', """
p96 = force_token()
setfield_gc(p0, p96, descr=<FieldP
pypy.interpreter.pyframe.PyFrame.vable_token .>)
- i97 = call_release_gil(91, i59, i10, i12, 1, descr=<Calli . iii
EF=7 OS=62>)
+ i97 = call_release_gil_i(91, i59, i10, i12, 1, descr=<Calli . iii
EF=7 OS=62>)
guard_not_forced(descr=...)
guard_no_exception(descr=...)
- p98 = call(ConstClass(fromrarith_int__r_uint), i97, descr=<Callr .
i EF=4>)
+ p98 = call_r(ConstClass(fromrarith_int__r_uint), i97, descr=<Callr
. i EF=4>)
guard_no_exception(descr=...)
""", ignore_ops=['guard_not_invalidated'])
@@ -354,7 +354,7 @@
loop, = log.loops_by_id('cfficall')
assert loop.match_by_id('cfficall', """
...
- f1 = call_release_gil(..., descr=<Calli 4 ii EF=7 OS=62>)
+ i1 = call_release_gil_i(..., descr=<Calli 4 ii EF=7 OS=62>)
...
""")
diff --git a/pypy/module/pypyjit/test_pypy_c/test_instance.py
b/pypy/module/pypyjit/test_pypy_c/test_instance.py
--- a/pypy/module/pypyjit/test_pypy_c/test_instance.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_instance.py
@@ -120,7 +120,7 @@
i59 = int_add_ovf(i57, 1)
guard_no_overflow(descr=...)
p60 = force_token()
- i61 = getfield_raw(..., descr=...)
+ i61 = getfield_raw_i(..., descr=...)
setfield_gc(ConstPtr(ptr39), i59, descr=...)
i62 = int_lt(i61, 0)
guard_false(i62, descr=...)
@@ -172,7 +172,7 @@
p72 = force_token()
p73 = force_token()
i74 = int_add(i58, 1)
- i75 = getfield_raw(..., descr=...)
+ i75 = getfield_raw_i(..., descr=...)
i76 = int_lt(i75, 0)
guard_false(i76, descr=...)
p77 = new_with_vtable(...)
diff --git a/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py
b/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py
--- a/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_micronumpy.py
@@ -266,7 +266,7 @@
i91 = int_add(i87, 1)
i93 = int_add(i89, 8)
i94 = int_add(i79, 1)
- i95 = getfield_raw(#, descr=<FieldS pypysig_long_struct.c_value 0>)
+ i95 = getfield_raw_i(#, descr=<FieldS pypysig_long_struct.c_value
0>)
setfield_gc(p97, i91, descr=<FieldS
pypy.module.micronumpy.iterators.IterState.inst_index .+>)
setfield_gc(p97, i93, descr=<FieldS
pypy.module.micronumpy.iterators.IterState.inst_offset .+>)
i96 = int_lt(i95, 0)
@@ -326,7 +326,7 @@
guard_not_invalidated(descr=...)
raw_store(i103, i132, 42.000000, descr=<ArrayF 8>)
i153 = int_add(i120, 1)
- i154 = getfield_raw(#, descr=<FieldS pypysig_long_struct.c_value
0>)
+ i154 = getfield_raw_i(#, descr=<FieldS pypysig_long_struct.c_value
0>)
setarrayitem_gc(p152, 1, 0, descr=<ArrayS .+>)
setarrayitem_gc(p152, 0, 0, descr=<ArrayS .+>)
setfield_gc(p158, i53, descr=<FieldS
pypy.module.micronumpy.iterators.IterState.inst_offset .+>)
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
@@ -1057,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/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/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/test/test_annrpython.py
b/rpython/annotator/test/test_annrpython.py
--- a/rpython/annotator/test/test_annrpython.py
+++ b/rpython/annotator/test/test_annrpython.py
@@ -4492,6 +4492,15 @@
with py.test.raises(annmodel.AnnotatorError):
a.build_types(f, [int])
+ def test_dict_can_be_none_ordering_issue(self):
+ def g(d):
+ return 42 in d
+ def f(n):
+ g(None)
+ g({})
+ a = self.RPythonAnnotator()
+ a.build_types(f, [int])
+
def g(n):
return [0, 1, 2, n]
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
@@ -46,6 +49,16 @@
return s_Bool
contains_SomeObject.can_only_throw = []
[email protected](SomeNone)
+def contains_SomeNone(annotator, obj, element):
+ # return False here for the case "... in None", because it can be later
+ # generalized to "... in d" where d is either None or the empty dict
+ # (which would also return the constant False)
+ s_bool = SomeBool()
+ s_bool.const = False
+ return s_bool
+contains_SomeNone.can_only_throw = []
+
@op.simple_call.register(SomeObject)
def simple_call_SomeObject(annotator, func, *args):
return annotator.annotation(func).call(
@@ -364,20 +377,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
-
[email protected](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
+
[email protected](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 +413,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 +466,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 +484,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/assembler.py
b/rpython/jit/backend/arm/assembler.py
--- a/rpython/jit/backend/arm/assembler.py
+++ b/rpython/jit/backend/arm/assembler.py
@@ -12,8 +12,7 @@
from rpython.jit.backend.arm.opassembler import ResOpAssembler
from rpython.jit.backend.arm.regalloc import (Regalloc,
CoreRegisterManager, check_imm_arg, VFPRegisterManager,
- operations as regalloc_operations,
- operations_with_guard as regalloc_operations_with_guard)
+ operations as regalloc_operations)
from rpython.jit.backend.llsupport import jitframe, rewrite
from rpython.jit.backend.llsupport.assembler import DEBUG_COUNTER,
debug_bridge, BaseAssembler
from rpython.jit.backend.llsupport.regalloc import get_scale,
valid_addressing_size
@@ -645,8 +644,10 @@
size_excluding_failure_stuff - loop_head)
def _assemble(self, regalloc, inputargs, operations):
+ self.guard_success_cc = c.cond_none
regalloc.compute_hint_frame_locations(operations)
self._walk_operations(inputargs, operations, regalloc)
+ assert self.guard_success_cc == c.cond_none
frame_depth = regalloc.get_final_frame_depth()
jump_target_descr = regalloc.jump_target_descr
if jump_target_descr is not None:
@@ -707,7 +708,7 @@
self.fixup_target_tokens(rawstart)
self.update_frame_depth(frame_depth)
if logger:
- logger.log_bridge(inputargs, operations, "rewritten",
+ logger.log_bridge(inputargs, operations, "rewritten", faildescr,
ops_offset=ops_offset)
self.teardown()
@@ -927,6 +928,7 @@
def _walk_operations(self, inputargs, operations, regalloc):
fcond = c.AL
self._regalloc = regalloc
+ regalloc.operations = operations
while regalloc.position() < len(operations) - 1:
regalloc.next_instruction()
i = regalloc.position()
@@ -934,20 +936,9 @@
op = operations[i]
self.mc.mark_op(op)
opnum = op.getopnum()
- if op.has_no_side_effect() and op.result not in regalloc.longevity:
+ if op.has_no_side_effect() and op not in regalloc.longevity:
regalloc.possibly_free_vars_for_op(op)
- elif self._regalloc.can_merge_with_next_guard(op, i, operations):
- guard = operations[i + 1]
- assert guard.is_guard()
- arglocs = regalloc_operations_with_guard[opnum](regalloc, op,
- guard, fcond)
- fcond = asm_operations_with_guard[opnum](self, op,
- guard, arglocs, regalloc, fcond)
- assert fcond is not None
- regalloc.next_instruction()
- regalloc.possibly_free_vars_for_op(guard)
- regalloc.possibly_free_vars(guard.getfailargs())
- elif not we_are_translated() and op.getopnum() == -124:
+ elif not we_are_translated() and op.getopnum() == -127:
regalloc.prepare_force_spill(op, fcond)
else:
arglocs = regalloc_operations[opnum](regalloc, op, fcond)
@@ -957,12 +948,13 @@
assert fcond is not None
if op.is_guard():
regalloc.possibly_free_vars(op.getfailargs())
- if op.result:
- regalloc.possibly_free_var(op.result)
+ if op.type != 'v':
+ regalloc.possibly_free_var(op)
regalloc.possibly_free_vars_for_op(op)
regalloc.free_temp_vars()
regalloc._check_invariants()
self.mc.mark_op(None) # end of the loop
+ regalloc.operations = None
def regalloc_emit_extra(self, op, arglocs, fcond, regalloc):
# for calls to a function with a specifically-supported OS_xxx
@@ -1517,21 +1509,11 @@
raise NotImplementedError(op)
-def notimplemented_op_with_guard(self, op, guard_op, arglocs, regalloc, fcond):
- print "[ARM/asm] %s with guard %s not implemented" % \
- (op.getopname(), guard_op.getopname())
- raise NotImplementedError(op)
-
asm_operations = [notimplemented_op] * (rop._LAST + 1)
-asm_operations_with_guard = [notimplemented_op_with_guard] * (rop._LAST + 1)
asm_extra_operations = {}
for name, value in ResOpAssembler.__dict__.iteritems():
- if name.startswith('emit_guard_'):
- opname = name[len('emit_guard_'):]
- num = getattr(rop, opname.upper())
- asm_operations_with_guard[num] = value
- elif name.startswith('emit_opx_'):
+ if name.startswith('emit_opx_'):
opname = name[len('emit_opx_'):]
num = getattr(EffectInfo, 'OS_' + opname.upper())
asm_extra_operations[num] = value
diff --git a/rpython/jit/backend/arm/conditions.py
b/rpython/jit/backend/arm/conditions.py
--- a/rpython/jit/backend/arm/conditions.py
+++ b/rpython/jit/backend/arm/conditions.py
@@ -13,11 +13,13 @@
GT = 0xC
LE = 0xD
AL = 0xE
+cond_none = -1
opposites = [NE, EQ, CC, CS, PL, MI, VC, VS, LS, HI, LT, GE, LE, GT, AL]
def get_opposite_of(operation):
+ assert operation >= 0
return opposites[operation]
# see mapping for floating poin according to
diff --git a/rpython/jit/backend/arm/helper/assembler.py
b/rpython/jit/backend/arm/helper/assembler.py
--- a/rpython/jit/backend/arm/helper/assembler.py
+++ b/rpython/jit/backend/arm/helper/assembler.py
@@ -2,37 +2,36 @@
from rpython.jit.backend.arm import conditions as c
from rpython.jit.backend.arm import registers as r
from rpython.jit.backend.arm.codebuilder import InstrBuilder
-from rpython.jit.metainterp.history import ConstInt, BoxInt, FLOAT
+from rpython.jit.metainterp.history import FLOAT
from rpython.rlib.rarithmetic import r_uint, r_longlong, intmask
from rpython.jit.metainterp.resoperation import rop
+
+def flush_cc(asm, condition, result_loc):
+ # After emitting an instruction that leaves a boolean result in
+ # a condition code (cc), call this. In the common case, result_loc
+ # will be set to 'fp' 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 asm.guard_success_cc == c.cond_none
+ if result_loc is r.fp:
+ asm.guard_success_cc = condition
+ else:
+ asm.mc.MOV_ri(result_loc.value, 1, condition)
+ asm.mc.MOV_ri(result_loc.value, 0, c.get_opposite_of(condition))
+
+
def gen_emit_op_unary_cmp(name, true_cond):
- false_cond = c.get_opposite_of(true_cond)
def f(self, op, arglocs, regalloc, fcond):
assert fcond is not None
reg, res = arglocs
self.mc.CMP_ri(reg.value, 0)
- self.mc.MOV_ri(res.value, 1, true_cond)
- self.mc.MOV_ri(res.value, 0, false_cond)
+ flush_cc(self, true_cond, res)
return fcond
f.__name__ = 'emit_op_%s' % name
return f
-def gen_emit_guard_unary_cmp(name, true_cond):
- false_cond = c.get_opposite_of(true_cond)
- def f(self, op, guard, arglocs, regalloc, fcond):
- assert fcond is not None
- assert guard is not None
- reg = arglocs[0]
- self.mc.CMP_ri(reg.value, 0)
- cond = true_cond
- guard_opnum = guard.getopnum()
- if guard_opnum == rop.GUARD_FALSE:
- cond = false_cond
- return self._emit_guard(guard, arglocs[1:], cond, save_exc=False)
- f.__name__ = 'emit_guard_%s' % name
- return f
-
def gen_emit_op_ri(name, opname):
ri_op = getattr(InstrBuilder, '%s_ri' % opname)
rr_op = getattr(InstrBuilder, '%s_rr' % opname)
@@ -51,7 +50,7 @@
helper = getattr(InstrBuilder, opname)
def f(self, op, arglocs, regalloc, fcond):
assert fcond is not None
- if op.result:
+ if op.type != 'v':
regs = r.caller_resp[1:] + [r.ip]
else:
regs = r.caller_resp
@@ -61,8 +60,7 @@
f.__name__ = 'emit_op_%s' % name
return f
-def gen_emit_cmp_op(name, condition):
- inv = c.get_opposite_of(condition)
+def gen_emit_cmp_op(name, true_cond):
def f(self, op, arglocs, regalloc, fcond):
l0, l1, res = arglocs
@@ -70,32 +68,11 @@
self.mc.CMP_ri(l0.value, imm=l1.getint(), cond=fcond)
else:
self.mc.CMP_rr(l0.value, l1.value, cond=fcond)
- self.mc.MOV_ri(res.value, 1, cond=condition)
- self.mc.MOV_ri(res.value, 0, cond=inv)
+ flush_cc(self, true_cond, res)
return fcond
f.__name__ = 'emit_op_%s' % name
return f
-def gen_emit_cmp_op_guard(name, true_cond):
- false_cond = c.get_opposite_of(true_cond)
- def f(self, op, guard, arglocs, regalloc, fcond):
- assert guard is not None
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit