[pypy-commit] pypy default: merge upstream
krono
noreply at buildbot.pypy.org
Wed Jul 24 18:14:03 CEST 2013
Author: Tobias Pape <tobias at netshed.de>
Branch:
Changeset: r65619:d63e416d3f3d
Date: 2013-05-06 11:32 +0200
http://bitbucket.org/pypy/pypy/changeset/d63e416d3f3d/
Log: merge upstream
diff --git a/lib_pypy/_ctypes/structure.py b/lib_pypy/_ctypes/structure.py
--- a/lib_pypy/_ctypes/structure.py
+++ b/lib_pypy/_ctypes/structure.py
@@ -167,7 +167,6 @@
return
if '_fields_' not in self.__dict__:
self._fields_ = []
- self._names = []
_set_shape(self, [], self._is_union)
__setattr__ = struct_setattr
diff --git a/pypy/doc/release-2.0.0.rst b/pypy/doc/release-2.0.0.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/release-2.0.0.rst
@@ -0,0 +1,61 @@
+============================
+PyPy 2.0 - Einstein Sandwich
+============================
+
+We're pleased to announce PyPy 2.0. This is a stable release that brings
+a swath of bugfixes, small performance improvements and compatibility fixes.
+
+You can download the PyPy 2.0 release here:
+
+ http://pypy.org/download.html
+
+The two biggest changes since PyPy 1.9 are:
+
+* stackless is now supported including greenlets, which means eventlet
+ and gevent should work (but read below about gevent)
+
+* PyPy now contains release 0.6 of `cffi`_ as a builtin module, which
+ is preferred way of calling C from Python that works well on PyPy
+
+.. _`cffi`: http://cffi.readthedocs.org
+
+What is PyPy?
+=============
+
+PyPy is a very compliant Python interpreter, almost a drop-in replacement for
+CPython 2.7. It's fast (`pypy 2.0 and cpython 2.7.3`_ performance comparison)
+due to its integrated tracing JIT compiler.
+
+This release supports x86 machines running Linux 32/64, Mac OS X 64 or
+Windows 32. Windows 64 work is still stalling, we would welcome a volunteer
+to handle that. ARM support is on the way and we're expecting to release
+an alpha ARM version shortly.
+
+.. _`pypy 2.0 and cpython 2.7.3`: http://speed.pypy.org
+
+Highlights
+==========
+
+* Stackless including greenlets should work. For gevent, you need to check
+ out `pypycore`_ and use the `pypy-hacks`_ branch of gevent.
+
+* cffi is now a module included with PyPy. (`cffi`_ also exists for
+ CPython; the two versions should be fully compatible.) It is the
+ preferred way of calling C from Python that works on PyPy.
+
+* Callbacks from C are now JITted, which means XML parsing is much faster.
+
+* A lot of speed improvements in various language corners, most of them small,
+ but speeding up some particular corners a lot.
+
+* The JIT was refactored to emit machine code which manipulates a "frame"
+ that lives on the heap rather than on the stack. This is what makes
+ Stackless work, and it could bring another future speed-up (not done yet).
+
+* A lot of stability issues fixed.
+
+.. _`pypycore`: https://github.com/gevent-on-pypy/pypycore/
+.. _`pypy-hacks`: https://github.com/schmir/gevent/tree/pypy-hacks
+
+Cheers,
+fijal, arigo and the PyPy team
diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-2.0.rst
copy from pypy/doc/whatsnew-head.rst
copy to pypy/doc/whatsnew-2.0.rst
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
@@ -1,140 +1,7 @@
======================
-What's new in PyPy 2.0
+What's new in PyPy 2.1
======================
-.. this is a revision shortly after release-2.0-beta1
-.. startrev: 0e6161a009c6
+.. this is a revision shortly after release-2.0
+.. startrev: a13c07067613
-.. branch: split-rpython
-Split rpython and pypy into seperate directories
-
-.. branch: callback-jit
-Callbacks from C are now better JITted
-
-.. branch: fix-jit-logs
-
-.. branch: remove-globals-in-jit
-
-.. branch: length-hint
-Implement __lenght_hint__ according to PEP 424
-
-.. branch: numpypy-longdouble
-Long double support for numpypy
-
-.. branch: numpypy-disable-longdouble
-Since r_longdouble support is missing, disable all longdouble and derivative
-dtypes using ENABLED_LONG_DOUBLE = False
-
-.. branch: numpypy-real-as-view
-Convert real, imag from ufuncs to views. This involves the beginning of
-view() functionality
-
-.. branch: indexing-by-array
-Adds indexing by scalar, adds int conversion from scalar and single element array,
-fixes compress, indexing by an array with a smaller shape and the indexed object.
-
-.. branch: str-dtype-improvement
-Allow concatenation of str and numeric arrays
-
-.. branch: signatures
-Improved RPython typing
-
-.. branch: rpython-bytearray
-Rudimentary support for bytearray in RPython
-
-.. branch: refactor-call_release_gil
-Fix a bug which caused cffi to return the wrong result when calling a C
-function which calls a Python callback which forces the frames
-
-.. branch: virtual-raw-mallocs
-JIT optimizations which make cffi calls even faster, by removing the need to
-allocate a temporary buffer where to store the arguments.
-
-.. branch: improve-docs-2
-Improve documents and straighten out links
-
-.. branch: fast-newarray
-Inline the fast path of newarray in the assembler.
-Disabled on ARM until we fix issues.
-
-.. branch: reflex-support
-Allow dynamic loading of a (Reflex) backend that implements the C-API needed
-to provide reflection information
-
-.. branches we don't care about
-.. branch: autoreds
-.. branch: kill-faking
-.. branch: improved_ebnfparse_error
-.. branch: task-decorator
-.. branch: fix-e4fa0b2
-.. branch: win32-fixes
-.. branch: numpy-unify-methods
-.. branch: fix-version-tool
-.. branch: popen2-removal
-.. branch: pickle-dumps
-.. branch: scalar_get_set
-
-.. branch: release-2.0-beta1
-
-.. branch: remove-PYPY_NOT_MAIN_FILE
-
-.. branch: missing-jit-operations
-
-.. branch: fix-lookinside-iff-oopspec
-Fixed the interaction between two internal tools for controlling the JIT.
-
-.. branch: inline-virtualref-2
-Better optimized certain types of frame accesses in the JIT, particularly
-around exceptions that escape the function they were raised in.
-
-.. branch: missing-ndarray-attributes
-Some missing attributes from ndarrays
-
-.. branch: cleanup-tests
-Consolidated the lib_pypy/pypy_test and pypy/module/test_lib_pypy tests into
-one directory for reduced confusion and so they all run nightly.
-
-.. branch: unquote-faster
-.. branch: urlparse-unquote-faster
-
-.. branch: signal-and-thread
-Add "__pypy__.thread.signals_enabled", a context manager. Can be used in a
-non-main thread to enable the processing of signal handlers in that thread.
-
-.. branch: coding-guide-update-rlib-refs
-.. branch: rlib-doc-rpython-refs
-.. branch: clean-up-remaining-pypy-rlib-refs
-
-.. branch: enumerate-rstr
-Support enumerate() over rstr types.
-
-.. branch: cleanup-numpypy-namespace
-Cleanup _numpypy and numpypy namespaces to more closely resemble numpy.
-
-.. branch: kill-flowobjspace
-Random cleanups to hide FlowObjSpace from public view.
-
-.. branch: vendor-rename
-
-.. branch: jitframe-on-heap
-Moves optimized JIT frames from stack to heap. As a side effect it enables
-stackless to work well with the JIT on PyPy. Also removes a bunch of code from
-the GC which fixes cannot find gc roots.
-
-.. branch: pycon2013-doc-fixes
-Documentation fixes after going through the docs at PyCon 2013 sprint.
-
-.. branch: extregistry-refactor
-
-.. branch: remove-list-smm
-.. branch: bridge-logging
-.. branch: curses_cffi
-cffi implementation of _curses
-
-.. branch: sqlite-cffi
-cffi implementation of sqlite3
-
-.. branch: release-2.0-beta2
-.. branch: unbreak-freebsd
-
-.. branch: virtualref-virtualizable
diff --git a/pypy/goal/getnightly.py b/pypy/goal/getnightly.py
--- a/pypy/goal/getnightly.py
+++ b/pypy/goal/getnightly.py
@@ -6,8 +6,14 @@
if sys.platform.startswith('linux'):
arch = 'linux'
+ cmd = 'wget "%s"'
+ tar = "tar -x -v --wildcards --strip-components=2 -f %s '*/bin/pypy'"
+if sys.platform.startswith('darwin'):
+ arch = 'osx'
+ cmd = 'curl -O "%s"'
+ tar = "tar -x -v --strip-components=2 -f %s '*/bin/pypy'"
else:
- print 'Cannot determine the platform, please update this scrip'
+ print 'Cannot determine the platform, please update this script'
sys.exit(1)
if sys.maxint == 2**63 - 1:
@@ -23,10 +29,9 @@
tmp = py.path.local.mkdtemp()
mydir = tmp.chdir()
print 'Downloading pypy to', tmp
-if os.system('wget "%s"' % url) != 0:
+if os.system(cmd % url) != 0:
sys.exit(1)
print 'Extracting pypy binary'
mydir.chdir()
-os.system("tar -x -v --wildcards --strip-components=2 -f %s '*/bin/pypy'" % tmp.join(filename))
-
+os.system(tar % tmp.join(filename))
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
@@ -85,3 +85,7 @@
from rpython.jit.backend import detect_cpu
model = detect_cpu.autodetect_main_model_and_size()
self.extra_interpdef('cpumodel', 'space.wrap(%r)' % model)
+ 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/__pypy__/test/test_special.py b/pypy/module/__pypy__/test/test_special.py
--- a/pypy/module/__pypy__/test/test_special.py
+++ b/pypy/module/__pypy__/test/test_special.py
@@ -62,3 +62,14 @@
assert list_strategy(l) == "empty"
o = 5
raises(TypeError, list_strategy, 5)
+
+
+class AppTestJitFeatures(object):
+ spaceconfig = {"translation.jit": True}
+
+ def test_jit_backend_features(self):
+ from __pypy__ import jit_backend_features
+ supported_types = jit_backend_features
+ assert isinstance(supported_types, list)
+ for x in supported_types:
+ assert x in ['floats', 'singlefloats', 'longlong']
diff --git a/pypy/module/_io/__init__.py b/pypy/module/_io/__init__.py
--- a/pypy/module/_io/__init__.py
+++ b/pypy/module/_io/__init__.py
@@ -38,5 +38,5 @@
def shutdown(self, space):
# at shutdown, flush all open streams. Ignore I/O errors.
- from pypy.module._io.interp_iobase import get_autoflushher
- get_autoflushher(space).flush_all(space)
+ from pypy.module._io.interp_iobase import get_autoflusher
+ get_autoflusher(space).flush_all(space)
diff --git a/pypy/module/_io/interp_iobase.py b/pypy/module/_io/interp_iobase.py
--- a/pypy/module/_io/interp_iobase.py
+++ b/pypy/module/_io/interp_iobase.py
@@ -47,7 +47,7 @@
self.w_dict = space.newdict()
self.__IOBase_closed = False
self.streamholder = None # needed by AutoFlusher
- get_autoflushher(space).add(self)
+ get_autoflusher(space).add(self)
def getdict(self, space):
return self.w_dict
@@ -103,7 +103,7 @@
space.call_method(self, "flush")
finally:
self.__IOBase_closed = True
- get_autoflushher(space).remove(self)
+ get_autoflusher(space).remove(self)
def flush_w(self, space):
if self._CLOSED():
@@ -363,5 +363,5 @@
else:
streamholder.autoflush(space)
-def get_autoflushher(space):
+def get_autoflusher(space):
return space.fromcache(AutoFlusher)
diff --git a/pypy/module/_random/interp_random.py b/pypy/module/_random/interp_random.py
--- a/pypy/module/_random/interp_random.py
+++ b/pypy/module/_random/interp_random.py
@@ -33,8 +33,8 @@
elif space.isinstance_w(w_n, space.w_long):
w_n = space.abs(w_n)
else:
- # XXX not perfectly like CPython
- w_n = space.abs(space.hash(w_n))
+ n = space.hash_w(w_n)
+ w_n = space.wrap(r_uint(n))
key = []
w_one = space.newint(1)
w_two = space.newint(2)
diff --git a/pypy/module/_random/test/test_random.py b/pypy/module/_random/test/test_random.py
--- a/pypy/module/_random/test/test_random.py
+++ b/pypy/module/_random/test/test_random.py
@@ -42,13 +42,14 @@
rnd1.setstate((-1, ) * 624 + (0, ))
def test_seed(self):
- import _random
+ import _random, sys
rnd = _random.Random()
rnd.seed()
different_nums = []
+ mask = sys.maxint * 2 + 1
for obj in ["spam and eggs", 3.14, 1+2j, 'a', tuple('abc')]:
nums = []
- for o in [obj, hash(obj), -hash(obj)]:
+ for o in [obj, hash(obj) & mask, -(hash(obj) & mask)]:
rnd.seed(o)
nums.append([rnd.random() for i in range(100)])
n1 = nums[0]
diff --git a/pypy/module/imp/importing.py b/pypy/module/imp/importing.py
--- a/pypy/module/imp/importing.py
+++ b/pypy/module/imp/importing.py
@@ -16,6 +16,8 @@
from rpython.rlib.objectmodel import we_are_translated, specialize
from pypy.module.sys.version import PYPY_VERSION
+_WIN32 = sys.platform == 'win32'
+
SEARCH_ERROR = 0
PY_SOURCE = 1
PY_COMPILED = 2
@@ -27,12 +29,8 @@
# PY_CODERESOURCE = 8
IMP_HOOK = 9
-if sys.platform == 'win32':
- SO = ".pyd"
-else:
- SO = ".so"
+SO = '.pyd' if _WIN32 else '.so'
DEFAULT_SOABI = 'pypy-%d%d' % PYPY_VERSION[:2]
-CHECK_FOR_PYW = sys.platform == 'win32'
@specialize.memo()
def get_so_extension(space):
@@ -64,7 +62,7 @@
return PY_SOURCE, ".py", "U"
# on Windows, also check for a .pyw file
- if CHECK_FOR_PYW:
+ if _WIN32:
pyfile = filepart + ".pyw"
if file_exists(pyfile):
return PY_SOURCE, ".pyw", "U"
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
@@ -119,6 +119,12 @@
""")
def test_array_of_floats(self):
+ try:
+ from __pypy__ import jit_backend_features
+ if 'singlefloats' not in jit_backend_features:
+ py.test.skip("test requres singlefloats support from the JIT backend")
+ except ImportError:
+ pass
def main():
from array import array
img = array('f', [21.5]*1000)
diff --git a/pypy/module/test_lib_pypy/ctypes_tests/test_structures.py b/pypy/module/test_lib_pypy/ctypes_tests/test_structures.py
--- a/pypy/module/test_lib_pypy/ctypes_tests/test_structures.py
+++ b/pypy/module/test_lib_pypy/ctypes_tests/test_structures.py
@@ -230,6 +230,17 @@
pt = POINT(y=2, x=1)
assert (pt.x, pt.y) == (1, 2)
+ def test_subclass_initializer(self):
+ class POINT(Structure):
+ _fields_ = [("x", c_int), ("y", c_int)]
+
+ class POSITION(POINT):
+ # A subclass without _fields_
+ pass
+ pos = POSITION(1, 2)
+ assert (pos.x, pos.y) == (1, 2)
+
+
def test_invalid_field_types(self):
class POINT(Structure):
pass
@@ -538,6 +549,7 @@
raises(AttributeError, setattr, X, "_fields_", [])
Y.__fields__ = []
+
class TestPatologicalCases(BaseCTypesTestChecker):
def test_structure_overloading_getattr(self):
class X(Structure):
diff --git a/pypy/objspace/std/stringobject.py b/pypy/objspace/std/stringobject.py
--- a/pypy/objspace/std/stringobject.py
+++ b/pypy/objspace/std/stringobject.py
@@ -39,12 +39,10 @@
def unicode_w(w_self, space):
# Use the default encoding.
- from pypy.objspace.std.unicodetype import unicode_from_string, \
- decode_object
+ from pypy.objspace.std.unicodetype import (unicode_from_string,
+ decode_object, _get_encoding_and_errors)
w_defaultencoding = space.call_function(space.sys.get(
'getdefaultencoding'))
- from pypy.objspace.std.unicodetype import _get_encoding_and_errors, \
- unicode_from_string, decode_object
encoding, errors = _get_encoding_and_errors(space, w_defaultencoding,
space.w_None)
if encoding is None and errors is None:
@@ -236,7 +234,7 @@
def str_title__String(space, w_self):
input = w_self._value
builder = StringBuilder(len(input))
- prev_letter=' '
+ prev_letter = ' '
for pos in range(len(input)):
ch = input[pos]
@@ -434,7 +432,7 @@
space.wrap("rjust() argument 2 must be a single character"))
d = u_arg - len(u_self)
- if d>0:
+ if d > 0:
fillchar = fillchar[0] # annotator hint: it's a single character
u_self = d * fillchar + u_self
@@ -450,7 +448,7 @@
space.wrap("ljust() argument 2 must be a single character"))
d = u_arg - len(u_self)
- if d>0:
+ if d > 0:
fillchar = fillchar[0] # annotator hint: it's a single character
u_self += d * fillchar
@@ -471,12 +469,12 @@
return space.newbool(self.find(sub) >= 0)
def str_find__String_String_ANY_ANY(space, w_self, w_sub, w_start, w_end):
- (self, start, end) = _convert_idx_params(space, w_self, w_start, w_end)
+ (self, start, end) = _convert_idx_params(space, w_self, w_start, w_end)
res = self.find(w_sub._value, start, end)
return space.wrap(res)
def str_rfind__String_String_ANY_ANY(space, w_self, w_sub, w_start, w_end):
- (self, start, end) = _convert_idx_params(space, w_self, w_start, w_end)
+ (self, start, end) = _convert_idx_params(space, w_self, w_start, w_end)
res = self.rfind(w_sub._value, start, end)
return space.wrap(res)
@@ -511,7 +509,7 @@
def str_index__String_String_ANY_ANY(space, w_self, w_sub, w_start, w_end):
- (self, start, end) = _convert_idx_params(space, w_self, w_start, w_end)
+ (self, start, end) = _convert_idx_params(space, w_self, w_start, w_end)
res = self.find(w_sub._value, start, end)
if res < 0:
raise OperationError(space.w_ValueError,
@@ -521,7 +519,7 @@
def str_rindex__String_String_ANY_ANY(space, w_self, w_sub, w_start, w_end):
- (self, start, end) = _convert_idx_params(space, w_self, w_start, w_end)
+ (self, start, end) = _convert_idx_params(space, w_self, w_start, w_end)
res = self.rfind(w_sub._value, start, end)
if res < 0:
raise OperationError(space.w_ValueError,
@@ -728,7 +726,7 @@
while 1:
#no sophisticated linebreak support now, '\r' just for passing adapted CPython test
if u_token[offset-1] == "\n" or u_token[offset-1] == "\r":
- break;
+ break
distance += 1
offset -= 1
if offset == 0:
@@ -738,7 +736,7 @@
#print '<offset:%d distance:%d tabsize:%d token:%s>' % (offset, distance, u_tabsize, u_token)
distance = (u_tabsize-distance) % u_tabsize
if distance == 0:
- distance=u_tabsize
+ distance = u_tabsize
return distance
@@ -760,14 +758,14 @@
for token in split:
#print "%d#%d -%s-" % (_tabindent(oldtoken,u_tabsize), u_tabsize, token)
- u_expanded += " " * _tabindent(oldtoken,u_tabsize) + token
+ u_expanded += " " * _tabindent(oldtoken, u_tabsize) + token
oldtoken = token
return wrapstr(space, u_expanded)
def str_splitlines__String_ANY(space, w_self, w_keepends):
- u_keepends = space.int_w(w_keepends) # truth value, but type checked
+ u_keepends = space.int_w(w_keepends) # truth value, but type checked
data = w_self._value
selflen = len(data)
strs_w = []
@@ -876,7 +874,6 @@
return wrapchar(space, str[ival])
def getitem__String_Slice(space, w_str, w_slice):
- w = space.wrap
s = w_str._value
length = len(s)
start, stop, step, sl = w_slice.indices4(space, length)
diff --git a/pypy/objspace/std/test/test_listobject.py b/pypy/objspace/std/test/test_listobject.py
--- a/pypy/objspace/std/test/test_listobject.py
+++ b/pypy/objspace/std/test/test_listobject.py
@@ -948,6 +948,9 @@
def test_setitem_slice_performance(self):
# because of a complexity bug, this used to take forever on a
# translated pypy. On CPython2.6 -A, it takes around 5 seconds.
+ import platform
+ if platform.machine().startswith('arm'):
+ skip("consumes too much memory for most ARM machines")
if self.runappdirect:
count = 16*1024*1024
else:
diff --git a/pypy/pytest-A.py b/pypy/pytest-A.py
--- a/pypy/pytest-A.py
+++ b/pypy/pytest-A.py
@@ -6,6 +6,7 @@
'interpreter/pyparser/test',
'interpreter/test',
'interpreter/test2',
+ 'module/test_lib_pypy',
'objspace/std/test',
],
}
diff --git a/rpython/jit/backend/arm/test/test_fficall.py b/rpython/jit/backend/arm/test/test_fficall.py
new file mode 100644
--- /dev/null
+++ b/rpython/jit/backend/arm/test/test_fficall.py
@@ -0,0 +1,23 @@
+import py
+from rpython.jit.metainterp.test import test_fficall
+from rpython.jit.backend.arm.test.support import JitARMMixin
+
+class TestFfiCall(JitARMMixin, test_fficall.FfiCallTests):
+ # for the individual tests see
+ # ====> ../../../metainterp/test/test_fficall.py
+
+ def _add_libffi_types_to_ll2types_maybe(self):
+ # this is needed by test_guard_not_forced_fails, because it produces a
+ # loop which reads the value of types.* in a variable, then a guard
+ # fail and we switch to blackhole: the problem is that at this point
+ # the blackhole interp has a real integer, but it needs to convert it
+ # back to a lltype pointer (which is handled by ll2ctypes, deeply in
+ # the logic). The workaround is to teach ll2ctypes in advance which
+ # are the addresses of the various types.* structures.
+ # Try to comment this code out and run the test to see how it fails :)
+ from rpython.rtyper.lltypesystem import rffi, lltype, ll2ctypes
+ from rpython.rlib.jit_libffi import types
+ for key, value in types.__dict__.iteritems():
+ if isinstance(value, lltype._ptr):
+ addr = rffi.cast(lltype.Signed, value)
+ ll2ctypes._int2obj[addr] = value
diff --git a/rpython/jit/backend/detect_cpu.py b/rpython/jit/backend/detect_cpu.py
--- a/rpython/jit/backend/detect_cpu.py
+++ b/rpython/jit/backend/detect_cpu.py
@@ -115,6 +115,14 @@
mod = __import__(modname, {}, {}, clsname)
return getattr(mod, clsname)
+
+def getcpufeatures(backend_name="auto"):
+ """NOT_RPYTHON"""
+ cpucls = getcpuclass(backend_name)
+ return [attr[len('supports_'):] for attr in dir(cpucls)
+ if attr.startswith('supports_')
+ and getattr(cpucls, attr)]
+
if __name__ == '__main__':
print autodetect()
print getcpuclassname()
diff --git a/rpython/jit/backend/test/test_detect_cpu.py b/rpython/jit/backend/test/test_detect_cpu.py
--- a/rpython/jit/backend/test/test_detect_cpu.py
+++ b/rpython/jit/backend/test/test_detect_cpu.py
@@ -31,3 +31,9 @@
def test_detect_main_model_and_size_from_platform():
info = autodetect_main_model_and_size()
assert detect_main_model_and_size_from_platform() == info
+
+def test_getcpufeatures():
+ features = getcpufeatures()
+ assert isinstance(features, list)
+ for x in features:
+ assert x in ['floats', 'singlefloats', 'longlong']
diff --git a/rpython/jit/codewriter/jtransform.py b/rpython/jit/codewriter/jtransform.py
--- a/rpython/jit/codewriter/jtransform.py
+++ b/rpython/jit/codewriter/jtransform.py
@@ -1751,7 +1751,7 @@
def rewrite_op_jit_ffi_save_result(self, op):
kind = op.args[0].value
- assert kind in ('int', 'float')
+ assert kind in ('int', 'float', 'longlong', 'singlefloat')
return SpaceOperation('libffi_save_result_%s' % kind, op.args[1:], None)
def rewrite_op_jit_force_virtual(self, op):
diff --git a/rpython/jit/metainterp/blackhole.py b/rpython/jit/metainterp/blackhole.py
--- a/rpython/jit/metainterp/blackhole.py
+++ b/rpython/jit/metainterp/blackhole.py
@@ -1351,24 +1351,39 @@
def bhimpl_ll_read_timestamp():
return read_timestamp()
- @arguments("cpu", "i", "i", "i")
- def bhimpl_libffi_save_result_int(self, cif_description, exchange_buffer, result):
- ARRAY = lltype.Ptr(rffi.CArray(lltype.Signed))
- cif_description = self.cast_int_to_ptr(cif_description, CIF_DESCRIPTION_P)
- exchange_buffer = self.cast_int_to_ptr(exchange_buffer, rffi.CCHARP)
+ def _libffi_save_result(self, cif_description, exchange_buffer, result):
+ ARRAY = lltype.Ptr(rffi.CArray(lltype.typeOf(result)))
+ cast_int_to_ptr = self.cpu.cast_int_to_ptr
+ cif_description = cast_int_to_ptr(cif_description, CIF_DESCRIPTION_P)
+ exchange_buffer = cast_int_to_ptr(exchange_buffer, rffi.CCHARP)
#
data_out = rffi.ptradd(exchange_buffer, cif_description.exchange_result)
rffi.cast(ARRAY, data_out)[0] = result
+ _libffi_save_result._annspecialcase_ = 'specialize:argtype(3)'
- @arguments("cpu", "i", "i", "f")
- def bhimpl_libffi_save_result_float(self, cif_description, exchange_buffer, result):
+ @arguments("self", "i", "i", "i")
+ def bhimpl_libffi_save_result_int(self, cif_description,
+ exchange_buffer, result):
+ self._libffi_save_result(cif_description, exchange_buffer, result)
+
+ @arguments("self", "i", "i", "f")
+ def bhimpl_libffi_save_result_float(self, cif_description,
+ exchange_buffer, result):
result = longlong.getrealfloat(result)
- ARRAY = lltype.Ptr(rffi.CArray(lltype.Float))
- cif_description = self.cast_int_to_ptr(cif_description, CIF_DESCRIPTION_P)
- exchange_buffer = self.cast_int_to_ptr(exchange_buffer, rffi.CCHARP)
- #
- data_out = rffi.ptradd(exchange_buffer, cif_description.exchange_result)
- rffi.cast(ARRAY, data_out)[0] = result
+ self._libffi_save_result(cif_description, exchange_buffer, result)
+
+ @arguments("self", "i", "i", "f")
+ def bhimpl_libffi_save_result_longlong(self, cif_description,
+ exchange_buffer, result):
+ # 32-bit only: 'result' is here a LongLong
+ assert longlong.is_longlong(lltype.typeOf(result))
+ self._libffi_save_result(cif_description, exchange_buffer, result)
+
+ @arguments("self", "i", "i", "i")
+ def bhimpl_libffi_save_result_singlefloat(self, cif_description,
+ exchange_buffer, result):
+ result = longlong.int2singlefloat(result)
+ self._libffi_save_result(cif_description, exchange_buffer, result)
# ----------
diff --git a/rpython/jit/metainterp/pyjitpl.py b/rpython/jit/metainterp/pyjitpl.py
--- a/rpython/jit/metainterp/pyjitpl.py
+++ b/rpython/jit/metainterp/pyjitpl.py
@@ -1190,8 +1190,8 @@
return self.metainterp.execute_and_record(rop.READ_TIMESTAMP, None)
@arguments("box", "box", "box")
- def opimpl_libffi_save_result_int(self, box_cif_description, box_exchange_buffer,
- box_result):
+ def _opimpl_libffi_save_result(self, box_cif_description,
+ box_exchange_buffer, box_result):
from rpython.rtyper.lltypesystem import llmemory
from rpython.rlib.jit_libffi import CIF_DESCRIPTION_P
from rpython.jit.backend.llsupport.ffisupport import get_arg_descr
@@ -1208,10 +1208,14 @@
assert ofs % itemsize == 0 # alignment check (result)
self.metainterp.history.record(rop.SETARRAYITEM_RAW,
[box_exchange_buffer,
- ConstInt(ofs // itemsize), box_result],
+ ConstInt(ofs // itemsize),
+ box_result],
None, descr)
- opimpl_libffi_save_result_float = opimpl_libffi_save_result_int
+ opimpl_libffi_save_result_int = _opimpl_libffi_save_result
+ opimpl_libffi_save_result_float = _opimpl_libffi_save_result
+ opimpl_libffi_save_result_longlong = _opimpl_libffi_save_result
+ opimpl_libffi_save_result_singlefloat = _opimpl_libffi_save_result
# ------------------------------
diff --git a/rpython/jit/metainterp/test/support.py b/rpython/jit/metainterp/test/support.py
--- a/rpython/jit/metainterp/test/support.py
+++ b/rpython/jit/metainterp/test/support.py
@@ -14,7 +14,10 @@
def _get_jitcodes(testself, CPUClass, func, values, type_system,
- supports_longlong=False, translationoptions={}, **kwds):
+ supports_floats=True,
+ supports_longlong=False,
+ supports_singlefloats=False,
+ translationoptions={}, **kwds):
from rpython.jit.codewriter import support
class FakeJitCell(object):
@@ -67,9 +70,16 @@
cw = codewriter.CodeWriter(cpu, [FakeJitDriverSD()])
cw.debug = True
testself.cw = cw
+ if supports_floats and not cpu.supports_floats:
+ py.test.skip("this test requires supports_floats=True")
+ if supports_longlong and not cpu.supports_longlong:
+ py.test.skip("this test requires supports_longlong=True")
+ if supports_singlefloats and not cpu.supports_singlefloats:
+ py.test.skip("this test requires supports_singlefloats=True")
policy = JitPolicy()
- policy.set_supports_floats(True)
+ policy.set_supports_floats(supports_floats)
policy.set_supports_longlong(supports_longlong)
+ policy.set_supports_singlefloats(supports_singlefloats)
graphs = cw.find_all_graphs(policy)
if kwds.get("backendopt"):
backend_optimizations(rtyper.annotator.translator, graphs=graphs)
diff --git a/rpython/jit/metainterp/test/test_fficall.py b/rpython/jit/metainterp/test/test_fficall.py
--- a/rpython/jit/metainterp/test/test_fficall.py
+++ b/rpython/jit/metainterp/test/test_fficall.py
@@ -5,13 +5,13 @@
from rpython.rtyper.lltypesystem import lltype, rffi
from rpython.rtyper.annlowlevel import llhelper
from rpython.jit.metainterp.test.support import LLJitMixin
-from rpython.jit.codewriter.longlong import is_longlong
+from rpython.jit.codewriter.longlong import is_longlong, is_64_bit
from rpython.rlib import jit
from rpython.rlib import jit_libffi
from rpython.rlib.jit_libffi import (types, CIF_DESCRIPTION, FFI_TYPE_PP,
jit_ffi_call, jit_ffi_save_result)
from rpython.rlib.unroll import unrolling_iterable
-from rpython.rlib.rarithmetic import intmask, r_longlong
+from rpython.rlib.rarithmetic import intmask, r_longlong, r_singlefloat
from rpython.rlib.longlong2float import float2longlong
def get_description(atypes, rtype):
@@ -45,7 +45,12 @@
class FfiCallTests(object):
- def _run(self, atypes, rtype, avalues, rvalue, expected_call_release_gil=1):
+ def _run(self, atypes, rtype, avalues, rvalue,
+ expected_call_release_gil=1,
+ supports_floats=True,
+ supports_longlong=True,
+ supports_singlefloats=True):
+
cif_description = get_description(atypes, rtype)
def verify(*args):
@@ -67,7 +72,11 @@
for avalue in unroll_avalues:
TYPE = rffi.CArray(lltype.typeOf(avalue))
data = rffi.ptradd(exchange_buffer, ofs)
- assert rffi.cast(lltype.Ptr(TYPE), data)[0] == avalue
+ got = rffi.cast(lltype.Ptr(TYPE), data)[0]
+ if lltype.typeOf(avalue) is lltype.SingleFloat:
+ got = float(got)
+ avalue = float(avalue)
+ assert got == avalue
ofs += 16
if rvalue is not None:
write_rvalue = rvalue
@@ -96,17 +105,30 @@
data = rffi.ptradd(exbuf, ofs)
res = rffi.cast(lltype.Ptr(TYPE), data)[0]
lltype.free(exbuf, flavor='raw')
+ if lltype.typeOf(res) is lltype.SingleFloat:
+ res = float(res)
return res
+ def matching_result(res, rvalue):
+ if rvalue is None:
+ return res == 654321
+ if isinstance(rvalue, r_singlefloat):
+ rvalue = float(rvalue)
+ return res == rvalue
+
with FakeFFI(fake_call_impl_any):
res = f()
- assert res == rvalue or (res, rvalue) == (654321, None)
- res = self.interp_operations(f, [])
+ assert matching_result(res, rvalue)
+ res = self.interp_operations(f, [],
+ supports_floats = supports_floats,
+ supports_longlong = supports_longlong,
+ supports_singlefloats = supports_singlefloats)
if is_longlong(FUNC.RESULT):
- # longlongs are passed around as floats inside the JIT, we
- # need to convert it back before checking the value
+ # longlongs are returned as floats, but that's just
+ # an inconvenience of interp_operations(). Normally both
+ # longlong and floats are passed around as longlongs.
res = float2longlong(res)
- assert res == rvalue or (res, rvalue) == (654321, None)
+ assert matching_result(res, rvalue)
self.check_operations_history(call_may_force=0,
call_release_gil=expected_call_release_gil)
@@ -119,14 +141,24 @@
[-123456*j for j in range(i)],
-42434445)
- def test_simple_call_float(self):
- self._run([types.double] * 2, types.double, [45.6, 78.9], -4.2)
+ def test_simple_call_float(self, **kwds):
+ self._run([types.double] * 2, types.double, [45.6, 78.9], -4.2, **kwds)
- def test_simple_call_longlong(self):
+ def test_simple_call_longlong(self, **kwds):
maxint32 = 2147483647
a = r_longlong(maxint32) + 1
b = r_longlong(maxint32) + 2
- self._run([types.slonglong] * 2, types.slonglong, [a, b], a)
+ self._run([types.slonglong] * 2, types.slonglong, [a, b], a, **kwds)
+
+ def test_simple_call_singlefloat_args(self):
+ self._run([types.float] * 2, types.double,
+ [r_singlefloat(10.5), r_singlefloat(31.5)],
+ -4.5)
+
+ def test_simple_call_singlefloat(self, **kwds):
+ self._run([types.float] * 2, types.float,
+ [r_singlefloat(10.5), r_singlefloat(31.5)],
+ r_singlefloat(-4.5), **kwds)
def test_simple_call_longdouble(self):
# longdouble is not supported, so we expect NOT to generate a call_release_gil
@@ -266,3 +298,20 @@
assert res == math.sin(1.23)
lltype.free(atypes, flavor='raw')
+
+ def test_simple_call_float_unsupported(self):
+ self.test_simple_call_float(supports_floats=False,
+ expected_call_release_gil=0)
+
+ def test_simple_call_longlong_unsupported(self):
+ self.test_simple_call_longlong(supports_longlong=False,
+ expected_call_release_gil=is_64_bit)
+
+ def test_simple_call_singlefloat_unsupported(self):
+ self.test_simple_call_singlefloat(supports_singlefloats=False,
+ expected_call_release_gil=0)
+
+ def test_simple_call_float_even_if_other_unsupported(self):
+ self.test_simple_call_float(supports_longlong=False,
+ supports_singlefloats=False)
+ # this is the default: expected_call_release_gil=1
diff --git a/rpython/memory/gctransform/transform.py b/rpython/memory/gctransform/transform.py
--- a/rpython/memory/gctransform/transform.py
+++ b/rpython/memory/gctransform/transform.py
@@ -281,11 +281,11 @@
def finish_helpers(self, backendopt=True):
if self.translator is not None:
self.mixlevelannotator.finish_annotate()
- self.finished_helpers = True
if self.translator is not None:
self.mixlevelannotator.finish_rtype()
if backendopt:
self.mixlevelannotator.backend_optimize()
+ self.finished_helpers = True
# Make sure that the database also sees all finalizers now.
# It is likely that the finalizers need special support there
newgcdependencies = self.ll_finalizers_ptrs
diff --git a/rpython/rlib/jit_libffi.py b/rpython/rlib/jit_libffi.py
--- a/rpython/rlib/jit_libffi.py
+++ b/rpython/rlib/jit_libffi.py
@@ -2,6 +2,7 @@
from rpython.rtyper.lltypesystem import lltype, rffi
from rpython.rtyper.extregistry import ExtRegistryEntry
from rpython.rlib import clibffi, jit
+from rpython.rlib.rarithmetic import r_longlong, r_singlefloat
from rpython.rlib.nonconst import NonConstant
@@ -107,12 +108,14 @@
reskind = types.getkind(cif_description.rtype)
if reskind == 'v':
jit_ffi_call_impl_void(cif_description, func_addr, exchange_buffer)
- elif reskind == 'f' or reskind == 'L': # L is for longlongs, on 32bit
- result = jit_ffi_call_impl_float(cif_description, func_addr, exchange_buffer)
- jit_ffi_save_result('float', cif_description, exchange_buffer, result)
elif reskind == 'i' or reskind == 'u':
- result = jit_ffi_call_impl_int(cif_description, func_addr, exchange_buffer)
- jit_ffi_save_result('int', cif_description, exchange_buffer, result)
+ _do_ffi_call_int(cif_description, func_addr, exchange_buffer)
+ elif reskind == 'f':
+ _do_ffi_call_float(cif_description, func_addr, exchange_buffer)
+ elif reskind == 'L': # L is for longlongs, on 32bit
+ _do_ffi_call_longlong(cif_description, func_addr, exchange_buffer)
+ elif reskind == 'S': # SingleFloat
+ _do_ffi_call_singlefloat(cif_description, func_addr, exchange_buffer)
else:
# the result kind is not supported: we disable the jit_ffi_call
# optimization by calling directly jit_ffi_call_impl_any, so the JIT
@@ -123,6 +126,30 @@
jit_ffi_call_impl_any(cif_description, func_addr, exchange_buffer)
+def _do_ffi_call_int(cif_description, func_addr, exchange_buffer):
+ result = jit_ffi_call_impl_int(cif_description, func_addr,
+ exchange_buffer)
+ jit_ffi_save_result('int', cif_description, exchange_buffer, result)
+
+def _do_ffi_call_float(cif_description, func_addr, exchange_buffer):
+ # a separate function in case the backend doesn't support floats
+ result = jit_ffi_call_impl_float(cif_description, func_addr,
+ exchange_buffer)
+ jit_ffi_save_result('float', cif_description, exchange_buffer, result)
+
+def _do_ffi_call_longlong(cif_description, func_addr, exchange_buffer):
+ # a separate function in case the backend doesn't support longlongs
+ result = jit_ffi_call_impl_longlong(cif_description, func_addr,
+ exchange_buffer)
+ jit_ffi_save_result('longlong', cif_description, exchange_buffer, result)
+
+def _do_ffi_call_singlefloat(cif_description, func_addr, exchange_buffer):
+ # a separate function in case the backend doesn't support singlefloats
+ result = jit_ffi_call_impl_singlefloat(cif_description, func_addr,
+ exchange_buffer)
+ jit_ffi_save_result('singlefloat', cif_description, exchange_buffer,result)
+
+
# we must return a NonConstant else we get the constant -1 as the result of
# the flowgraph, and the codewriter does not produce a box for the
# result. Note that when not-jitted, the result is unused, but when jitted the
@@ -139,6 +166,16 @@
return NonConstant(-1.0)
@jit.oopspec("libffi_call(cif_description,func_addr,exchange_buffer)")
+def jit_ffi_call_impl_longlong(cif_description, func_addr, exchange_buffer):
+ jit_ffi_call_impl_any(cif_description, func_addr, exchange_buffer)
+ return r_longlong(-1)
+
+ at jit.oopspec("libffi_call(cif_description,func_addr,exchange_buffer)")
+def jit_ffi_call_impl_singlefloat(cif_description, func_addr, exchange_buffer):
+ jit_ffi_call_impl_any(cif_description, func_addr, exchange_buffer)
+ return r_singlefloat(-1.0)
+
+ at jit.oopspec("libffi_call(cif_description,func_addr,exchange_buffer)")
def jit_ffi_call_impl_void(cif_description, func_addr, exchange_buffer):
jit_ffi_call_impl_any(cif_description, func_addr, exchange_buffer)
return None
@@ -175,7 +212,7 @@
def compute_result_annotation(self, kind_s, *args_s):
from rpython.annotator import model as annmodel
assert isinstance(kind_s, annmodel.SomeString)
- assert kind_s.const in ('int', 'float')
+ assert kind_s.const in ('int', 'float', 'longlong', 'singlefloat')
def specialize_call(self, hop):
hop.exception_cannot_occur()
diff --git a/testrunner/runner.py b/testrunner/runner.py
--- a/testrunner/runner.py
+++ b/testrunner/runner.py
@@ -329,7 +329,7 @@
self.collect_one_testdir(testdirs, reldir,
[self.reltoroot(t) for t in entries
if self.is_test_py_file(t)])
- return
+ break
for p1 in entries:
if p1.check(dir=1, link=0):
More information about the pypy-commit
mailing list