Author: Matti Picus <[email protected]>
Branch: cpyext-pickle
Changeset: r84846:b576bccbfa9d
Date: 2016-05-31 20:37 +0300
http://bitbucket.org/pypy/pypy/changeset/b576bccbfa9d/
Log: merge default into branch
diff too long, truncating to 2000 out of 5510 lines
diff --git a/.hgtags b/.hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -23,3 +23,5 @@
3260adbeba4a8b6659d1cc0d0b41f266769b74da release-5.1
b0a649e90b6642251fb4a765fe5b27a97b1319a9 release-5.1.1
80ef432a32d9baa4b3c5a54c215e8ebe499f6374 release-5.1.2
+40497617ae91caa1a394d8be6f9cd2de31cb0628 release-pypy3.3-v5.2
+40497617ae91caa1a394d8be6f9cd2de31cb0628 release-pypy3.3-v5.2
diff --git a/lib-python/2.7/subprocess.py b/lib-python/2.7/subprocess.py
--- a/lib-python/2.7/subprocess.py
+++ b/lib-python/2.7/subprocess.py
@@ -834,54 +834,63 @@
c2pread, c2pwrite = None, None
errread, errwrite = None, None
+ ispread = False
if stdin is None:
p2cread =
_subprocess.GetStdHandle(_subprocess.STD_INPUT_HANDLE)
if p2cread is None:
p2cread, _ = _subprocess.CreatePipe(None, 0)
+ ispread = True
elif stdin == PIPE:
p2cread, p2cwrite = _subprocess.CreatePipe(None, 0)
+ ispread = True
elif isinstance(stdin, int):
p2cread = msvcrt.get_osfhandle(stdin)
else:
# Assuming file-like object
p2cread = msvcrt.get_osfhandle(stdin.fileno())
- p2cread = self._make_inheritable(p2cread)
+ p2cread = self._make_inheritable(p2cread, ispread)
# We just duplicated the handle, it has to be closed at the end
to_close.add(p2cread)
if stdin == PIPE:
to_close.add(p2cwrite)
+ ispwrite = False
if stdout is None:
c2pwrite =
_subprocess.GetStdHandle(_subprocess.STD_OUTPUT_HANDLE)
if c2pwrite is None:
_, c2pwrite = _subprocess.CreatePipe(None, 0)
+ ispwrite = True
elif stdout == PIPE:
c2pread, c2pwrite = _subprocess.CreatePipe(None, 0)
+ ispwrite = True
elif isinstance(stdout, int):
c2pwrite = msvcrt.get_osfhandle(stdout)
else:
# Assuming file-like object
c2pwrite = msvcrt.get_osfhandle(stdout.fileno())
- c2pwrite = self._make_inheritable(c2pwrite)
+ c2pwrite = self._make_inheritable(c2pwrite, ispwrite)
# We just duplicated the handle, it has to be closed at the end
to_close.add(c2pwrite)
if stdout == PIPE:
to_close.add(c2pread)
+ ispwrite = False
if stderr is None:
errwrite =
_subprocess.GetStdHandle(_subprocess.STD_ERROR_HANDLE)
if errwrite is None:
_, errwrite = _subprocess.CreatePipe(None, 0)
+ ispwrite = True
elif stderr == PIPE:
errread, errwrite = _subprocess.CreatePipe(None, 0)
+ ispwrite = True
elif stderr == STDOUT:
- errwrite = c2pwrite.handle # pass id to not close it
+ errwrite = c2pwrite
elif isinstance(stderr, int):
errwrite = msvcrt.get_osfhandle(stderr)
else:
# Assuming file-like object
errwrite = msvcrt.get_osfhandle(stderr.fileno())
- errwrite = self._make_inheritable(errwrite)
+ errwrite = self._make_inheritable(errwrite, ispwrite)
# We just duplicated the handle, it has to be closed at the end
to_close.add(errwrite)
if stderr == PIPE:
@@ -892,13 +901,14 @@
errread, errwrite), to_close
- def _make_inheritable(self, handle):
+ def _make_inheritable(self, handle, close=False):
"""Return a duplicate of handle, which is inheritable"""
dupl = _subprocess.DuplicateHandle(_subprocess.GetCurrentProcess(),
handle, _subprocess.GetCurrentProcess(), 0, 1,
_subprocess.DUPLICATE_SAME_ACCESS)
- # If the initial handle was obtained with CreatePipe, close it.
- if not isinstance(handle, int):
+ # PyPy: If the initial handle was obtained with CreatePipe,
+ # close it.
+ if close:
handle.Close()
return dupl
diff --git a/lib_pypy/_pypy_interact.py b/lib_pypy/_pypy_interact.py
--- a/lib_pypy/_pypy_interact.py
+++ b/lib_pypy/_pypy_interact.py
@@ -6,7 +6,7 @@
irc_header = "And now for something completely different"
-def interactive_console(mainmodule=None, quiet=False):
+def interactive_console(mainmodule=None, quiet=False, future_flags=0):
# set sys.{ps1,ps2} just before invoking the interactive interpreter. This
# mimics what CPython does in pythonrun.c
if not hasattr(sys, 'ps1'):
@@ -37,15 +37,17 @@
raise ImportError
from pyrepl.simple_interact import run_multiline_interactive_console
except ImportError:
- run_simple_interactive_console(mainmodule)
+ run_simple_interactive_console(mainmodule, future_flags=future_flags)
else:
- run_multiline_interactive_console(mainmodule)
+ run_multiline_interactive_console(mainmodule,
future_flags=future_flags)
-def run_simple_interactive_console(mainmodule):
+def run_simple_interactive_console(mainmodule, future_flags=0):
import code
if mainmodule is None:
import __main__ as mainmodule
console = code.InteractiveConsole(mainmodule.__dict__, filename='<stdin>')
+ if future_flags:
+ console.compile.compiler.flags |= future_flags
# some parts of code.py are copied here because it seems to be impossible
# to start an interactive console without printing at least one line
# of banner
diff --git a/lib_pypy/_subprocess.py b/lib_pypy/_subprocess.py
--- a/lib_pypy/_subprocess.py
+++ b/lib_pypy/_subprocess.py
@@ -4,6 +4,9 @@
subprocess module on Windows.
"""
+import sys
+if sys.platform != 'win32':
+ raise ImportError("The '_subprocess' module is only available on Windows")
# Declare external Win32 functions
diff --git a/lib_pypy/pyrepl/simple_interact.py
b/lib_pypy/pyrepl/simple_interact.py
--- a/lib_pypy/pyrepl/simple_interact.py
+++ b/lib_pypy/pyrepl/simple_interact.py
@@ -43,11 +43,13 @@
return short
return text
-def run_multiline_interactive_console(mainmodule=None):
+def run_multiline_interactive_console(mainmodule=None, future_flags=0):
import code
if mainmodule is None:
import __main__ as mainmodule
console = code.InteractiveConsole(mainmodule.__dict__, filename='<stdin>')
+ if future_flags:
+ console.compile.compiler.flags |= future_flags
def more_lines(unicodetext):
# ooh, look at the hack:
diff --git a/pypy/doc/build.rst b/pypy/doc/build.rst
--- a/pypy/doc/build.rst
+++ b/pypy/doc/build.rst
@@ -70,9 +70,6 @@
bz2
libbz2
-lzma (PyPy3 only)
- liblzma
-
pyexpat
libexpat1
@@ -98,11 +95,16 @@
tk
tk-dev
+lzma (PyPy3 only)
+ liblzma
+
+To run untranslated tests, you need the Boehm garbage collector libgc.
+
On Debian, this is the command to install all build-time dependencies::
apt-get install gcc make libffi-dev pkg-config libz-dev libbz2-dev \
libsqlite3-dev libncurses-dev libexpat1-dev libssl-dev libgdbm-dev \
- tk-dev libgc-dev
+ tk-dev libgc-dev liblzma-dev
For the optional lzma module on PyPy3 you will also need ``liblzma-dev``.
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
@@ -49,6 +49,13 @@
release-0.6
+CPython 3.3 compatible versions
+-------------------------------
+
+.. toctree::
+
+ release-pypy3.3-v5.2-alpha1.rst
+
CPython 3.2 compatible versions
-------------------------------
diff --git a/pypy/doc/release-pypy3.3-v5.2-alpha1.rst
b/pypy/doc/release-pypy3.3-v5.2-alpha1.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/release-pypy3.3-v5.2-alpha1.rst
@@ -0,0 +1,69 @@
+===================
+PyPy3 v5.2 alpha 1
+===================
+
+We're pleased to announce the first alpha release of PyPy3.3 v5.2. This is the
+first release of PyPy which targets Python 3.3 (3.3.5) compatibility.
+
+We would like to thank all of the people who donated_ to the `py3k proposal`_
+for supporting the work that went into this and future releases.
+
+You can download the PyPy3.3 v5.2 alpha 1 release here:
+
+ http://pypy.org/download.html#python-3-3-5-compatible-pypy3-3-v5-2
+
+Highlights
+==========
+
+* Python 3.3.5 support!
+
+ - Being an early alpha release, there are some `missing features`_ such as a
+ `PEP 393-like space efficient string representation`_ and `known issues`_
+ including performance regressions (e.g. issue `#2305`_). The focus for this
+ release has been updating to 3.3 compatibility. Windows is also not yet
+ supported.
+
+* `ensurepip`_ is also included (it's only included in CPython 3 >= 3.4).
+
+What is PyPy?
+==============
+
+PyPy is a very compliant Python interpreter, almost a drop-in replacement for
+CPython 2.7.10 and one day 3.3.5. It's fast due to its integrated tracing JIT
+compiler.
+
+We also welcome developers of other `dynamic languages`_ to see what RPython
+can do for them.
+
+This release supports:
+
+ * **x86** machines on most common operating systems except Windows
+ (Linux 32/64, Mac OS X 64, OpenBSD, FreeBSD),
+
+ * newer **ARM** hardware (ARMv6 or ARMv7, with VFPv3) running Linux,
+
+ * big- and little-endian variants of **PPC64** running Linux,
+
+ * **s390x** running Linux
+
+Please try it out and let us know what you think. We welcome feedback, we know
+you are using PyPy, please tell us about it!
+
+We'd especially like to thank these people for their contributions to this
+release:
+
+Manuel Jacob, Ronan Lamy, Mark Young, Amaury Forgeot d'Arc, Philip Jenvey,
+Martin Matusiak, Vasily Kuznetsov, Matti Picus, Armin Rigo and many others.
+
+Cheers
+
+The PyPy Team
+
+.. _donated:
http://morepypy.blogspot.com/2012/01/py3k-and-numpy-first-stage-thanks-to.html
+.. _`py3k proposal`: http://pypy.org/py3donate.html
+.. _`PEP 393-like space efficient string representation`:
https://bitbucket.org/pypy/pypy/issues/2309/optimized-unicode-representation
+.. _`missing features`:
https://bitbucket.org/pypy/pypy/issues?status=new&status=open&component=PyPy3+%28running+Python+3.x%29&kind=enhancement
+.. _`known issues`:
https://bitbucket.org/pypy/pypy/issues?status=new&status=open&component=PyPy3%20%28running%20Python%203.x%29
+.. _`#2305`: https://bitbucket.org/pypy/pypy/issues/2305
+.. _`ensurepip`:
https://docs.python.org/3/library/ensurepip.html#module-ensurepip
+.. _`dynamic languages`: http://pypyjs.org
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
@@ -105,3 +105,24 @@
Fix some warnings when compiling CPython C extension modules
.. branch: syntax_fix
+
+.. branch: remove-raisingops
+
+Remove most of the _ovf, _zer and _val operations from RPython. Kills
+quite some code internally, and allows the JIT to do better
+optimizations: for example, app-level code like ``x / 2`` or ``x % 2``
+can now be turned into ``x >> 1`` or ``x & 1``, even if x is possibly
+negative.
+
+.. branch: cpyext-old-buffers
+
+Generalize cpyext old-style buffers to more than just str/buffer, add support
for mmap
+
+.. branch: numpy-includes
+
+Move _numpypy headers into a directory so they are not picked up by upstream
numpy, scipy
+This allows building upstream numpy and scipy in pypy via cpyext
+
+.. branch: traceviewer-common-merge-point-formats
+
+Teach RPython JIT's off-line traceviewer the most common ``debug_merge_point``
formats.
\ No newline at end of file
diff --git a/pypy/doc/whatsnew-pypy3-5.1.1-alpha1.rst
b/pypy/doc/whatsnew-pypy3-5.1.1-alpha1.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/whatsnew-pypy3-5.1.1-alpha1.rst
@@ -0,0 +1,10 @@
+=================================
+What's new in PyPy3 5.1.1 alpha 1
+=================================
+
+.. A recent revision, ignoring all other branches for this release
+.. startrev: 29d14733e007
+
+.. branch: py3.3
+
+Python 3.3 compatibility
diff --git a/pypy/doc/windows.rst b/pypy/doc/windows.rst
--- a/pypy/doc/windows.rst
+++ b/pypy/doc/windows.rst
@@ -238,6 +238,15 @@
for use. The release packaging script will pick up the tcltk runtime in the lib
directory and put it in the archive.
+The lzma compression library
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+Python 3.3 ship with CFFI wrappers for the lzma library, which can be
+downloaded from this site http://tukaani.org/xz. Python 3.3-3.5 use version
+5.0.5, a prebuilt version can be downloaded from
+http://tukaani.org/xz/xz-5.0.5-windows.zip, check the signature
+http://tukaani.org/xz/xz-5.0.5-windows.zip.sig
+
Using the mingw compiler
------------------------
diff --git a/pypy/interpreter/app_main.py b/pypy/interpreter/app_main.py
--- a/pypy/interpreter/app_main.py
+++ b/pypy/interpreter/app_main.py
@@ -583,6 +583,12 @@
if hasattr(signal, 'SIGXFSZ'):
signal.signal(signal.SIGXFSZ, signal.SIG_IGN)
+ # Pre-load the default encoder (controlled by PYTHONIOENCODING) now.
+ # This is needed before someone mucks up with sys.path (or even adds
+ # a unicode string to it, leading to infinite recursion when we try
+ # to encode it during importing). Note: very obscure. Issue #2314.
+ str(u'')
+
def inspect_requested():
# We get an interactive prompt in one of the following three cases:
#
@@ -603,6 +609,11 @@
((inspect or (readenv and real_getenv('PYTHONINSPECT')))
and sys.stdin.isatty()))
+ try:
+ from _ast import PyCF_ACCEPT_NULL_BYTES
+ except ImportError:
+ PyCF_ACCEPT_NULL_BYTES = 0
+ future_flags = [0]
success = True
try:
@@ -613,7 +624,9 @@
@hidden_applevel
def run_it():
- exec run_command in mainmodule.__dict__
+ co_cmd = compile(run_command, '<module>', 'exec')
+ exec co_cmd in mainmodule.__dict__
+ future_flags[0] = co_cmd.co_flags
success = run_toplevel(run_it)
elif run_module:
# handle the "-m" command
@@ -625,11 +638,6 @@
# handle the case where no command/filename/module is specified
# on the command-line.
- try:
- from _ast import PyCF_ACCEPT_NULL_BYTES
- except ImportError:
- PyCF_ACCEPT_NULL_BYTES = 0
-
# update sys.path *after* loading site.py, in case there is a
# "site.py" file in the script's directory. Only run this if we're
# executing the interactive prompt, if we're running a script we
@@ -656,6 +664,7 @@
'exec',
PyCF_ACCEPT_NULL_BYTES)
exec co_python_startup in mainmodule.__dict__
+ future_flags[0] = co_python_startup.co_flags
mainmodule.__file__ = python_startup
run_toplevel(run_it)
try:
@@ -673,6 +682,7 @@
co_stdin = compile(sys.stdin.read(), '<stdin>', 'exec',
PyCF_ACCEPT_NULL_BYTES)
exec co_stdin in mainmodule.__dict__
+ future_flags[0] = co_stdin.co_flags
mainmodule.__file__ = '<stdin>'
success = run_toplevel(run_it)
else:
@@ -702,7 +712,20 @@
args = (runpy._run_module_as_main, '__main__', False)
else:
# no. That's the normal path, "pypy stuff.py".
- args = (execfile, filename, mainmodule.__dict__)
+ # This includes the logic from execfile(), tweaked
+ # to grab the future_flags at the end.
+ @hidden_applevel
+ def run_it():
+ f = file(filename, 'rU')
+ try:
+ source = f.read()
+ finally:
+ f.close()
+ co_main = compile(source.rstrip()+"\n", filename,
+ 'exec', PyCF_ACCEPT_NULL_BYTES)
+ exec co_main in mainmodule.__dict__
+ future_flags[0] = co_main.co_flags
+ args = (run_it,)
success = run_toplevel(*args)
except SystemExit as e:
@@ -715,12 +738,21 @@
# start a prompt if requested
if inspect_requested():
try:
+ import __future__
from _pypy_interact import interactive_console
pypy_version_info = getattr(sys, 'pypy_version_info',
sys.version_info)
irc_topic = pypy_version_info[3] != 'final' or (
readenv and os.getenv('PYPY_IRC_TOPIC'))
+ flags = 0
+ for fname in __future__.all_feature_names:
+ feature = getattr(__future__, fname)
+ if future_flags[0] & feature.compiler_flag:
+ flags |= feature.compiler_flag
+ kwds = {}
+ if flags:
+ kwds['future_flags'] = flags
success = run_toplevel(interactive_console, mainmodule,
- quiet=not irc_topic)
+ quiet=not irc_topic, **kwds)
except SystemExit as e:
status = e.code
else:
diff --git a/pypy/interpreter/test/test_app_main.py
b/pypy/interpreter/test/test_app_main.py
--- a/pypy/interpreter/test/test_app_main.py
+++ b/pypy/interpreter/test/test_app_main.py
@@ -76,6 +76,11 @@
print 'Goodbye2' # should not be reached
""")
+script_with_future = getscript("""
+ from __future__ import division
+ from __future__ import print_function
+ """)
+
class TestParseCommandLine:
def check_options(self, options, sys_argv, **expected):
@@ -445,6 +450,31 @@
finally:
os.environ['PYTHONSTARTUP'] = old
+ def test_future_in_executed_script(self):
+ child = self.spawn(['-i', script_with_future])
+ child.expect('>>> ')
+ child.sendline('x=1; print(x/2, 3/4)')
+ child.expect('0.5 0.75')
+
+ def test_future_in_python_startup(self, monkeypatch):
+ monkeypatch.setenv('PYTHONSTARTUP', script_with_future)
+ child = self.spawn([])
+ child.expect('>>> ')
+ child.sendline('x=1; print(x/2, 3/4)')
+ child.expect('0.5 0.75')
+
+ def test_future_in_cmd(self):
+ child = self.spawn(['-i', '-c', 'from __future__ import division'])
+ child.expect('>>> ')
+ child.sendline('x=1; x/2; 3/4')
+ child.expect('0.5')
+ child.expect('0.75')
+
+ def test_cmd_co_name(self):
+ child = self.spawn(['-c',
+ 'import sys; print sys._getframe(0).f_code.co_name'])
+ child.expect('<module>')
+
def test_ignore_python_inspect(self):
os.environ['PYTHONINSPECT_'] = '1'
try:
diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py
--- a/pypy/interpreter/typedef.py
+++ b/pypy/interpreter/typedef.py
@@ -12,7 +12,8 @@
class TypeDef(object):
- def __init__(self, __name, __base=None, __total_ordering__=None,
**rawdict):
+ def __init__(self, __name, __base=None, __total_ordering__=None,
+ __buffer=None, **rawdict):
"NOT_RPYTHON: initialization-time only"
self.name = __name
if __base is None:
@@ -22,6 +23,8 @@
else:
bases = [__base]
self.bases = bases
+ assert __buffer in {None, 'read-write', 'read'}, "Unknown value for
__buffer"
+ self.buffer = __buffer
self.heaptype = False
self.hasdict = '__dict__' in rawdict
# no __del__: use an RPython _finalize_() method and register_finalizer
diff --git a/pypy/module/__pypy__/interp_intop.py
b/pypy/module/__pypy__/interp_intop.py
--- a/pypy/module/__pypy__/interp_intop.py
+++ b/pypy/module/__pypy__/interp_intop.py
@@ -2,6 +2,19 @@
from rpython.rtyper.lltypesystem import lltype
from rpython.rtyper.lltypesystem.lloperation import llop
from rpython.rlib.rarithmetic import r_uint, intmask
+from rpython.rlib import jit
+
+
+# XXX maybe temporary: hide llop.int_{floordiv,mod} from the JIT,
+# because now it expects only Python-style divisions, not the
+# C-style divisions of these two ll operations
[email protected]_look_inside
+def _int_floordiv(n, m):
+ return llop.int_floordiv(lltype.Signed, n, m)
+
[email protected]_look_inside
+def _int_mod(n, m):
+ return llop.int_mod(lltype.Signed, n, m)
@unwrap_spec(n=int, m=int)
@@ -18,11 +31,11 @@
@unwrap_spec(n=int, m=int)
def int_floordiv(space, n, m):
- return space.wrap(llop.int_floordiv(lltype.Signed, n, m))
+ return space.wrap(_int_floordiv(n, m))
@unwrap_spec(n=int, m=int)
def int_mod(space, n, m):
- return space.wrap(llop.int_mod(lltype.Signed, n, m))
+ return space.wrap(_int_mod(n, m))
@unwrap_spec(n=int, m=int)
def int_lshift(space, n, m):
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -161,12 +161,13 @@
if copy_numpy_headers:
try:
- dstdir.mkdir('numpy')
+ dstdir.mkdir('_numpypy')
+ dstdir.mkdir('_numpypy/numpy')
except py.error.EEXIST:
pass
- numpy_dstdir = dstdir / 'numpy'
+ numpy_dstdir = dstdir / '_numpypy' / 'numpy'
- numpy_include_dir = include_dir / 'numpy'
+ numpy_include_dir = include_dir / '_numpypy' / 'numpy'
numpy_headers = numpy_include_dir.listdir('*.h') +
numpy_include_dir.listdir('*.inl')
_copy_header_files(numpy_headers, numpy_dstdir)
diff --git a/pypy/module/cpyext/include/numpy/README
b/pypy/module/cpyext/include/_numpypy/numpy/README
rename from pypy/module/cpyext/include/numpy/README
rename to pypy/module/cpyext/include/_numpypy/numpy/README
diff --git a/pypy/module/cpyext/include/numpy/__multiarray_api.h
b/pypy/module/cpyext/include/_numpypy/numpy/__multiarray_api.h
rename from pypy/module/cpyext/include/numpy/__multiarray_api.h
rename to pypy/module/cpyext/include/_numpypy/numpy/__multiarray_api.h
diff --git a/pypy/module/cpyext/include/numpy/arrayobject.h
b/pypy/module/cpyext/include/_numpypy/numpy/arrayobject.h
rename from pypy/module/cpyext/include/numpy/arrayobject.h
rename to pypy/module/cpyext/include/_numpypy/numpy/arrayobject.h
diff --git a/pypy/module/cpyext/include/numpy/ndarraytypes.h
b/pypy/module/cpyext/include/_numpypy/numpy/ndarraytypes.h
rename from pypy/module/cpyext/include/numpy/ndarraytypes.h
rename to pypy/module/cpyext/include/_numpypy/numpy/ndarraytypes.h
diff --git a/pypy/module/cpyext/include/numpy/npy_3kcompat.h
b/pypy/module/cpyext/include/_numpypy/numpy/npy_3kcompat.h
rename from pypy/module/cpyext/include/numpy/npy_3kcompat.h
rename to pypy/module/cpyext/include/_numpypy/numpy/npy_3kcompat.h
diff --git a/pypy/module/cpyext/include/numpy/npy_common.h
b/pypy/module/cpyext/include/_numpypy/numpy/npy_common.h
rename from pypy/module/cpyext/include/numpy/npy_common.h
rename to pypy/module/cpyext/include/_numpypy/numpy/npy_common.h
diff --git a/pypy/module/cpyext/include/numpy/old_defines.h
b/pypy/module/cpyext/include/_numpypy/numpy/old_defines.h
rename from pypy/module/cpyext/include/numpy/old_defines.h
rename to pypy/module/cpyext/include/_numpypy/numpy/old_defines.h
diff --git a/pypy/module/cpyext/include/cStringIO.h
b/pypy/module/cpyext/include/cStringIO.h
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/include/cStringIO.h
@@ -0,0 +1,73 @@
+#ifndef Py_CSTRINGIO_H
+#define Py_CSTRINGIO_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+/*
+
+ This header provides access to cStringIO objects from C.
+ Functions are provided for calling cStringIO objects and
+ macros are provided for testing whether you have cStringIO
+ objects.
+
+ Before calling any of the functions or macros, you must initialize
+ the routines with:
+
+ PycString_IMPORT
+
+ This would typically be done in your init function.
+
+*/
+
+#define PycStringIO_CAPSULE_NAME "cStringIO.cStringIO_CAPI"
+
+#define PycString_IMPORT \
+ PycStringIO = ((struct PycStringIO_CAPI*)PyCapsule_Import(\
+ PycStringIO_CAPSULE_NAME, 0))
+
+/* Basic functions to manipulate cStringIO objects from C */
+
+static struct PycStringIO_CAPI {
+
+ /* Read a string from an input object. If the last argument
+ is -1, the remainder will be read.
+ */
+ int(*cread)(PyObject *, char **, Py_ssize_t);
+
+ /* Read a line from an input object. Returns the length of the read
+ line as an int and a pointer inside the object buffer as char** (so
+ the caller doesn't have to provide its own buffer as destination).
+ */
+ int(*creadline)(PyObject *, char **);
+
+ /* Write a string to an output object*/
+ int(*cwrite)(PyObject *, const char *, Py_ssize_t);
+
+ /* Get the output object as a Python string (returns new reference). */
+ PyObject *(*cgetvalue)(PyObject *);
+
+ /* Create a new output object */
+ PyObject *(*NewOutput)(int);
+
+ /* Create an input object from a Python string
+ (copies the Python string reference).
+ */
+ PyObject *(*NewInput)(PyObject *);
+
+ /* The Python types for cStringIO input and output objects.
+ Note that you can do input on an output object.
+ */
+ PyTypeObject *InputType, *OutputType;
+
+} *PycStringIO;
+
+/* These can be used to test if you have one */
+#define PycStringIO_InputCheck(O) \
+ (0) /* Py_TYPE(O)==PycStringIO->InputType) */
+#define PycStringIO_OutputCheck(O) \
+ (0) /* Py_TYPE(O)==PycStringIO->OutputType) */
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_CSTRINGIO_H */
diff --git a/pypy/module/cpyext/src/ndarrayobject.c
b/pypy/module/cpyext/src/ndarrayobject.c
--- a/pypy/module/cpyext/src/ndarrayobject.c
+++ b/pypy/module/cpyext/src/ndarrayobject.c
@@ -1,7 +1,7 @@
#include "Python.h"
#include "pypy_numpy.h"
-#include "numpy/arrayobject.h"
+#include "_numpypy/numpy/arrayobject.h"
#include <string.h> /* memset, memcpy */
void
diff --git a/pypy/module/cpyext/test/test_abstract.py
b/pypy/module/cpyext/test/test_abstract.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/test/test_abstract.py
@@ -0,0 +1,106 @@
+from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
+import pytest
+
+class AppTestBufferProtocol(AppTestCpythonExtensionBase):
+ """Tests for the old buffer protocol."""
+
+ def w_get_buffer_support(self):
+ return self.import_extension('buffer_support', [
+ ("charbuffer_as_string", "METH_O",
+ """
+ char *ptr;
+ Py_ssize_t size;
+ if (PyObject_AsCharBuffer(args, &ptr, &size) < 0)
+ return NULL;
+ return PyString_FromStringAndSize(ptr, size);
+ """),
+ ("check_readbuffer", "METH_O",
+ """
+ return PyBool_FromLong(PyObject_CheckReadBuffer(args));
+ """),
+ ("readbuffer_as_string", "METH_O",
+ """
+ const void *ptr;
+ Py_ssize_t size;
+ if (PyObject_AsReadBuffer(args, &ptr, &size) < 0)
+ return NULL;
+ return PyString_FromStringAndSize((char*)ptr, size);
+ """),
+ ("writebuffer_as_string", "METH_O",
+ """
+ void *ptr;
+ Py_ssize_t size;
+ if (PyObject_AsWriteBuffer(args, &ptr, &size) < 0)
+ return NULL;
+ return PyString_FromStringAndSize((char*)ptr, size);
+ """),
+ ("zero_out_writebuffer", "METH_O",
+ """
+ void *ptr;
+ Py_ssize_t size;
+ Py_ssize_t i;
+ if (PyObject_AsWriteBuffer(args, &ptr, &size) < 0)
+ return NULL;
+ for (i = 0; i < size; i++) {
+ ((char*)ptr)[i] = 0;
+ }
+ Py_RETURN_NONE;
+ """),
+ ])
+
+ def test_string(self):
+ buffer_support = self.get_buffer_support()
+
+ s = 'a\0x'
+
+ assert buffer_support.check_readbuffer(s)
+ assert s == buffer_support.readbuffer_as_string(s)
+ assert raises(TypeError, buffer_support.writebuffer_as_string, s)
+ assert s == buffer_support.charbuffer_as_string(s)
+
+ def test_buffer(self):
+ buffer_support = self.get_buffer_support()
+
+ s = 'a\0x'
+ buf = buffer(s)
+
+ assert buffer_support.check_readbuffer(buf)
+ assert s == buffer_support.readbuffer_as_string(buf)
+ assert raises(TypeError, buffer_support.writebuffer_as_string, buf)
+ assert s == buffer_support.charbuffer_as_string(buf)
+
+ def test_mmap(self):
+ import mmap
+ buffer_support = self.get_buffer_support()
+
+ s = 'a\0x'
+ mm = mmap.mmap(-1, 3)
+ mm[:] = s
+
+ assert buffer_support.check_readbuffer(mm)
+ assert s == buffer_support.readbuffer_as_string(mm)
+ assert s == buffer_support.writebuffer_as_string(mm)
+ assert s == buffer_support.charbuffer_as_string(mm)
+
+ s = '\0' * 3
+ buffer_support.zero_out_writebuffer(mm)
+ assert s == ''.join(mm)
+ assert s == buffer_support.readbuffer_as_string(mm)
+ assert s == buffer_support.writebuffer_as_string(mm)
+ assert s == buffer_support.charbuffer_as_string(mm)
+
+ s = '\0' * 3
+ ro_mm = mmap.mmap(-1, 3, access=mmap.ACCESS_READ)
+ assert buffer_support.check_readbuffer(ro_mm)
+ assert s == buffer_support.readbuffer_as_string(ro_mm)
+ assert raises(TypeError, buffer_support.writebuffer_as_string, ro_mm)
+ assert s == buffer_support.charbuffer_as_string(ro_mm)
+
+ def test_nonbuffer(self):
+ # e.g. int
+ buffer_support = self.get_buffer_support()
+
+ assert not buffer_support.check_readbuffer(42)
+ assert raises(TypeError, buffer_support.readbuffer_as_string, 42)
+ assert raises(TypeError, buffer_support.writebuffer_as_string, 42)
+ assert raises(TypeError, buffer_support.charbuffer_as_string, 42)
diff --git a/pypy/module/cpyext/test/test_bytesobject.py
b/pypy/module/cpyext/test/test_bytesobject.py
--- a/pypy/module/cpyext/test/test_bytesobject.py
+++ b/pypy/module/cpyext/test/test_bytesobject.py
@@ -415,12 +415,15 @@
lenp = lltype.malloc(Py_ssize_tP.TO, 1, flavor='raw')
w_text = space.wrap("text")
- assert api.PyObject_AsCharBuffer(w_text, bufp, lenp) == 0
+ ref = make_ref(space, w_text)
+ prev_refcnt = ref.c_ob_refcnt
+ assert api.PyObject_AsCharBuffer(ref, bufp, lenp) == 0
+ assert ref.c_ob_refcnt == prev_refcnt
assert lenp[0] == 4
assert rffi.charp2str(bufp[0]) == 'text'
-
lltype.free(bufp, flavor='raw')
lltype.free(lenp, flavor='raw')
+ api.Py_DecRef(ref)
def test_intern(self, space, api):
buf = rffi.str2charp("test")
diff --git a/pypy/module/cpyext/test/test_cpyext.py
b/pypy/module/cpyext/test/test_cpyext.py
--- a/pypy/module/cpyext/test/test_cpyext.py
+++ b/pypy/module/cpyext/test/test_cpyext.py
@@ -136,7 +136,7 @@
"""Base class for all cpyext tests."""
spaceconfig = dict(usemodules=['cpyext', 'thread', '_rawffi', 'array',
'itertools', 'time', 'binascii',
- 'micronumpy',
+ 'micronumpy', 'mmap'
])
enable_leak_checking = True
diff --git a/pypy/module/cpyext/test/test_ndarrayobject.py
b/pypy/module/cpyext/test/test_ndarrayobject.py
--- a/pypy/module/cpyext/test/test_ndarrayobject.py
+++ b/pypy/module/cpyext/test/test_ndarrayobject.py
@@ -1,4 +1,5 @@
import py
+import os
from pypy.module.cpyext.test.test_api import BaseApiTest
from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
from rpython.rtyper.lltypesystem import rffi, lltype
@@ -236,8 +237,10 @@
except:
skip('numpy not importable')
else:
- cls.w_numpy_include = cls.space.wrap([])
-
+ numpy_incl = os.path.abspath(os.path.dirname(__file__) +
+ '/../include/_numpypy')
+ assert os.path.exists(numpy_incl)
+ cls.w_numpy_include = cls.space.wrap([numpy_incl])
def test_ndarray_object_c(self):
mod = self.import_extension('foo', [
diff --git a/pypy/module/cpyext/typeobject.py b/pypy/module/cpyext/typeobject.py
--- a/pypy/module/cpyext/typeobject.py
+++ b/pypy/module/cpyext/typeobject.py
@@ -486,13 +486,40 @@
@cpython_api([PyObject, Py_ssize_tP], lltype.Signed, header=None,
error=CANNOT_FAIL)
-def str_segcount(space, w_obj, ref):
+def bf_segcount(space, w_obj, ref):
if ref:
ref[0] = space.len_w(w_obj)
return 1
@cpython_api([PyObject, Py_ssize_t, rffi.VOIDPP], lltype.Signed,
header=None, error=-1)
+def bf_getreadbuffer(space, w_buf, segment, ref):
+ if segment != 0:
+ raise oefmt(space.w_SystemError,
+ "accessing non-existent segment")
+ buf = space.readbuf_w(w_buf)
+ address = buf.get_raw_address()
+ ref[0] = address
+ return len(buf)
+
+@cpython_api([PyObject, Py_ssize_t, rffi.CCHARPP], lltype.Signed,
+ header=None, error=-1)
+def bf_getcharbuffer(space, w_buf, segment, ref):
+ return bf_getreadbuffer(space, w_buf, segment, rffi.cast(rffi.VOIDPP, ref))
+
+@cpython_api([PyObject, Py_ssize_t, rffi.VOIDPP], lltype.Signed,
+ header=None, error=-1)
+def bf_getwritebuffer(space, w_buf, segment, ref):
+ if segment != 0:
+ raise oefmt(space.w_SystemError,
+ "accessing non-existent segment")
+
+ buf = space.writebuf_w(w_buf)
+ ref[0] = buf.get_raw_address()
+ return len(buf)
+
+@cpython_api([PyObject, Py_ssize_t, rffi.VOIDPP], lltype.Signed,
+ header=None, error=-1)
def str_getreadbuffer(space, w_str, segment, ref):
from pypy.module.cpyext.bytesobject import PyString_AsString
if segment != 0:
@@ -506,16 +533,8 @@
@cpython_api([PyObject, Py_ssize_t, rffi.CCHARPP], lltype.Signed,
header=None, error=-1)
-def str_getcharbuffer(space, w_str, segment, ref):
- from pypy.module.cpyext.bytesobject import PyString_AsString
- if segment != 0:
- raise oefmt(space.w_SystemError,
- "accessing non-existent string segment")
- pyref = make_ref(space, w_str)
- ref[0] = PyString_AsString(space, pyref)
- # Stolen reference: the object has better exist somewhere else
- Py_DecRef(space, pyref)
- return space.len_w(w_str)
+def str_getcharbuffer(space, w_buf, segment, ref):
+ return str_getreadbuffer(space, w_buf, segment, rffi.cast(rffi.VOIDPP,
ref))
@cpython_api([PyObject, Py_ssize_t, rffi.VOIDPP], lltype.Signed,
header=None, error=-1)
@@ -523,33 +542,59 @@
from pypy.module.cpyext.bufferobject import PyBufferObject
if segment != 0:
raise oefmt(space.w_SystemError,
- "accessing non-existent string segment")
+ "accessing non-existent buffer segment")
py_buf = rffi.cast(PyBufferObject, pyref)
ref[0] = py_buf.c_b_ptr
- #Py_DecRef(space, pyref)
return py_buf.c_b_size
-def setup_string_buffer_procs(space, pto):
+@cpython_api([PyObject, Py_ssize_t, rffi.CCHARPP], lltype.Signed,
+ header=None, error=-1)
+def buf_getcharbuffer(space, w_buf, segment, ref):
+ return buf_getreadbuffer(space, w_buf, segment, rffi.cast(rffi.VOIDPP,
ref))
+
+def setup_buffer_procs(space, w_type, pto):
+ bufspec = w_type.layout.typedef.buffer
+ if bufspec is None:
+ # not a buffer
+ return
c_buf = lltype.malloc(PyBufferProcs, flavor='raw', zero=True)
lltype.render_immortal(c_buf)
- c_buf.c_bf_getsegcount = llhelper(str_segcount.api_func.functype,
- str_segcount.api_func.get_wrapper(space))
- c_buf.c_bf_getreadbuffer = llhelper(str_getreadbuffer.api_func.functype,
- str_getreadbuffer.api_func.get_wrapper(space))
- c_buf.c_bf_getcharbuffer = llhelper(str_getcharbuffer.api_func.functype,
- str_getcharbuffer.api_func.get_wrapper(space))
+ c_buf.c_bf_getsegcount = llhelper(bf_segcount.api_func.functype,
+ bf_segcount.api_func.get_wrapper(space))
+ if space.is_w(w_type, space.w_str):
+ # Special case: str doesn't support get_raw_address(), so we have a
+ # custom get*buffer that instead gives the address of the char* in the
+ # PyStringObject*!
+ c_buf.c_bf_getreadbuffer = llhelper(
+ str_getreadbuffer.api_func.functype,
+ str_getreadbuffer.api_func.get_wrapper(space))
+ c_buf.c_bf_getcharbuffer = llhelper(
+ str_getcharbuffer.api_func.functype,
+ str_getcharbuffer.api_func.get_wrapper(space))
+ elif space.is_w(w_type, space.w_buffer):
+ # Special case: we store a permanent address on the cpyext wrapper,
+ # so we'll reuse that.
+ # Note: we could instead store a permanent address on the buffer
object,
+ # and use get_raw_address()
+ c_buf.c_bf_getreadbuffer = llhelper(
+ buf_getreadbuffer.api_func.functype,
+ buf_getreadbuffer.api_func.get_wrapper(space))
+ c_buf.c_bf_getcharbuffer = llhelper(
+ buf_getcharbuffer.api_func.functype,
+ buf_getcharbuffer.api_func.get_wrapper(space))
+ else:
+ # use get_raw_address()
+ c_buf.c_bf_getreadbuffer = llhelper(bf_getreadbuffer.api_func.functype,
+
bf_getreadbuffer.api_func.get_wrapper(space))
+ c_buf.c_bf_getcharbuffer = llhelper(bf_getcharbuffer.api_func.functype,
+
bf_getcharbuffer.api_func.get_wrapper(space))
+ if bufspec == 'read-write':
+ c_buf.c_bf_getwritebuffer = llhelper(
+ bf_getwritebuffer.api_func.functype,
+ bf_getwritebuffer.api_func.get_wrapper(space))
pto.c_tp_as_buffer = c_buf
pto.c_tp_flags |= Py_TPFLAGS_HAVE_GETCHARBUFFER
-def setup_buffer_buffer_procs(space, pto):
- c_buf = lltype.malloc(PyBufferProcs, flavor='raw', zero=True)
- lltype.render_immortal(c_buf)
- c_buf.c_bf_getsegcount = llhelper(str_segcount.api_func.functype,
- str_segcount.api_func.get_wrapper(space))
- c_buf.c_bf_getreadbuffer = llhelper(buf_getreadbuffer.api_func.functype,
- buf_getreadbuffer.api_func.get_wrapper(space))
- pto.c_tp_as_buffer = c_buf
-
@cpython_api([PyObject], lltype.Void, header=None)
def type_dealloc(space, obj):
from pypy.module.cpyext.object import PyObject_dealloc
@@ -613,10 +658,7 @@
subtype_dealloc.api_func.functype,
subtype_dealloc.api_func.get_wrapper(space))
# buffer protocol
- if space.is_w(w_type, space.w_str):
- setup_string_buffer_procs(space, pto)
- if space.is_w(w_type, space.w_buffer):
- setup_buffer_buffer_procs(space, pto)
+ setup_buffer_procs(space, w_type, pto)
pto.c_tp_free = llhelper(PyObject_Free.api_func.functype,
PyObject_Free.api_func.get_wrapper(space))
diff --git a/pypy/module/micronumpy/compile.py
b/pypy/module/micronumpy/compile.py
--- a/pypy/module/micronumpy/compile.py
+++ b/pypy/module/micronumpy/compile.py
@@ -125,7 +125,8 @@
return None
def issubtype_w(self, w_sub, w_type):
- return w_sub is w_type
+ is_root(w_type)
+ return NonConstant(True)
def isinstance_w(self, w_obj, w_tp):
try:
@@ -414,6 +415,10 @@
def warn(self, w_msg, w_warn_type):
pass
+def is_root(w_obj):
+ assert isinstance(w_obj, W_Root)
+is_root.expecting = W_Root
+
class FloatObject(W_Root):
tp = FakeSpace.w_float
def __init__(self, floatval):
diff --git a/pypy/module/mmap/interp_mmap.py b/pypy/module/mmap/interp_mmap.py
--- a/pypy/module/mmap/interp_mmap.py
+++ b/pypy/module/mmap/interp_mmap.py
@@ -280,7 +280,7 @@
raise mmap_error(space, e)
return space.wrap(self)
-W_MMap.typedef = TypeDef("mmap.mmap",
+W_MMap.typedef = TypeDef("mmap.mmap", None, None, "read-write",
__new__ = interp2app(mmap),
close = interp2app(W_MMap.close),
read_byte = interp2app(W_MMap.read_byte),
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
@@ -262,7 +262,7 @@
[i0]
i1 = int_add(i0, 1)
i2 = int_sub(i1, 10)
- i3 = int_floordiv(i2, 100)
+ i3 = int_xor(i2, 100)
i4 = int_mul(i1, 1000)
jump(i4)
"""
@@ -298,7 +298,7 @@
[i0]
i1 = int_add(i0, 1)
i2 = int_sub(i1, 10)
- i3 = int_floordiv(i2, 100)
+ i3 = int_xor(i2, 100)
i4 = int_mul(i1, 1000)
jump(i4)
"""
diff --git a/pypy/module/pypyjit/test_pypy_c/test_shift.py
b/pypy/module/pypyjit/test_pypy_c/test_shift.py
--- a/pypy/module/pypyjit/test_pypy_c/test_shift.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_shift.py
@@ -47,26 +47,74 @@
res = 0
a = 0
while a < 300:
- assert a >= 0
- assert 0 <= b <= 10
- res = a/b # ID: div
+ res1 = a/b # ID: div
+ res2 = a/2 # ID: shift
+ res3 = a/11 # ID: mul
+ res += res1 + res2 + res3
a += 1
return res
#
log = self.run(main, [3])
- assert log.result == 99
+ assert log.result == main(3)
loop, = log.loops_by_filename(self.filepath)
- if sys.maxint == 2147483647:
- SHIFT = 31
+ assert loop.match_by_id('div', """
+ i56 = int_eq(i48, %d)
+ i57 = int_and(i56, i37)
+ guard_false(i57, descr=...)
+ i1 = call_i(_, i48, i3, descr=...)
+ """ % (-sys.maxint-1,))
+ assert loop.match_by_id('shift', """
+ i1 = int_rshift(i2, 1)
+ """)
+ if sys.maxint > 2**32:
+ args = (63, -5030930201920786804, 3)
else:
- SHIFT = 63
- assert loop.match_by_id('div', """
- i10 = int_floordiv(i6, i7)
- i11 = int_mul(i10, i7)
- i12 = int_sub(i6, i11)
- i14 = int_rshift(i12, %d)
- i15 = int_add(i10, i14)
- """ % SHIFT)
+ args = (31, -1171354717, 3)
+ assert loop.match_by_id('mul', """
+ i2 = int_rshift(i1, %d)
+ i3 = int_xor(i1, i2)
+ i4 = uint_mul_high(i3, %d)
+ i5 = uint_rshift(i4, %d)
+ i6 = int_xor(i5, i2)
+ """ % args)
+
+ def test_modulo_optimization(self):
+ def main(b):
+ res = 0
+ a = 0
+ while a < 300:
+ res1 = a%b # ID: mod
+ res2 = a%2 # ID: and
+ res3 = a%11 # ID: mul
+ res += res1 + res2 + res3
+ a += 1
+ return res
+ #
+ log = self.run(main, [3])
+ assert log.result == main(3)
+ loop, = log.loops_by_filename(self.filepath)
+ assert loop.match_by_id('mod', """
+ i56 = int_eq(i48, %d)
+ i57 = int_and(i56, i37)
+ guard_false(i57, descr=...)
+ i1 = call_i(_, i48, i3, descr=...)
+ """ % (-sys.maxint-1,))
+ assert loop.match_by_id('and', """
+ i1 = int_and(i2, 1)
+ """)
+ if sys.maxint > 2**32:
+ args = (63, -5030930201920786804, 3)
+ else:
+ args = (31, -1171354717, 3)
+ assert loop.match_by_id('mul', """
+ i2 = int_rshift(i1, %d)
+ i3 = int_xor(i1, i2)
+ i4 = uint_mul_high(i3, %d)
+ i5 = uint_rshift(i4, %d)
+ i6 = int_xor(i5, i2)
+ i7 = int_mul(i6, 11)
+ i8 = int_sub(i1, i7)
+ """ % args)
def test_division_to_rshift_allcases(self):
"""
diff --git a/pypy/module/pypyjit/test_pypy_c/test_string.py
b/pypy/module/pypyjit/test_pypy_c/test_string.py
--- a/pypy/module/pypyjit/test_pypy_c/test_string.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_string.py
@@ -1,11 +1,6 @@
import sys
from pypy.module.pypyjit.test_pypy_c.test_00_model import BaseTestPyPyC
-if sys.maxint == 2147483647:
- SHIFT = 31
-else:
- SHIFT = 63
-
# XXX review the <Call> descrs to replace some EF=5 with EF=4 (elidable)
@@ -28,10 +23,7 @@
guard_true(i14, descr=...)
guard_not_invalidated(descr=...)
i16 = int_eq(i6, %d)
- i15 = int_mod(i6, i10)
- i17 = int_rshift(i15, %d)
- i18 = int_and(i10, i17)
- i19 = int_add(i15, i18)
+ i19 = call_i(ConstClass(ll_int_mod__Signed_Signed), i6, i10,
descr=<Calli . ii EF=0 OS=14>)
i21 = int_lt(i19, 0)
guard_false(i21, descr=...)
i22 = int_ge(i19, i10)
@@ -49,7 +41,7 @@
i34 = int_add(i6, 1)
--TICK--
jump(..., descr=...)
- """ % (-sys.maxint-1, SHIFT))
+ """ % (-sys.maxint-1,))
def test_long(self):
def main(n):
@@ -62,19 +54,25 @@
log = self.run(main, [1100], import_site=True)
assert log.result == main(1100)
loop, = log.loops_by_filename(self.filepath)
+ if sys.maxint > 2**32:
+ args = (63, -3689348814741910323, 3)
+ else:
+ args = (31, -858993459, 3)
assert loop.match("""
i11 = int_lt(i6, i7)
guard_true(i11, descr=...)
guard_not_invalidated(descr=...)
i13 = int_eq(i6, %d) # value provided below
- i15 = int_mod(i6, 10)
- i17 = int_rshift(i15, %d) # value provided below
- i18 = int_and(10, i17)
- i19 = int_add(i15, i18)
- i21 = int_lt(i19, 0)
- guard_false(i21, descr=...)
- i22 = int_ge(i19, 10)
- guard_false(i22, descr=...)
+
+ # "mod 10" block:
+ i79 = int_rshift(i6, %d)
+ i80 = int_xor(i6, i79)
+ i82 = uint_mul_high(i80, %d)
+ i84 = uint_rshift(i82, %d)
+ i85 = int_xor(i84, i79)
+ i87 = int_mul(i85, 10)
+ i19 = int_sub(i6, i87)
+
i23 = strgetitem(p10, i19)
p25 = newstr(1)
strsetitem(p25, 0, i23)
@@ -89,7 +87,7 @@
guard_no_overflow(descr=...)
--TICK--
jump(..., descr=...)
- """ % (-sys.maxint-1, SHIFT))
+ """ % ((-sys.maxint-1,)+args))
def test_str_mod(self):
def main(n):
diff --git a/pypy/objspace/std/bufferobject.py
b/pypy/objspace/std/bufferobject.py
--- a/pypy/objspace/std/bufferobject.py
+++ b/pypy/objspace/std/bufferobject.py
@@ -135,7 +135,7 @@
return space.wrap(rffi.cast(lltype.Signed, ptr))
W_Buffer.typedef = TypeDef(
- "buffer",
+ "buffer", None, None, "read-write",
__doc__ = """\
buffer(object [, offset[, size]])
diff --git a/pypy/objspace/std/bytesobject.py b/pypy/objspace/std/bytesobject.py
--- a/pypy/objspace/std/bytesobject.py
+++ b/pypy/objspace/std/bytesobject.py
@@ -848,7 +848,7 @@
W_BytesObject.typedef = TypeDef(
- "str", basestring_typedef,
+ "str", basestring_typedef, None, "read",
__new__ = interp2app(W_BytesObject.descr_new),
__doc__ = """str(object='') -> string
diff --git a/pypy/objspace/std/newformat.py b/pypy/objspace/std/newformat.py
--- a/pypy/objspace/std/newformat.py
+++ b/pypy/objspace/std/newformat.py
@@ -7,6 +7,7 @@
from rpython.rlib import rstring, runicode, rlocale, rfloat, jit
from rpython.rlib.objectmodel import specialize
from rpython.rlib.rfloat import copysign, formatd
+from rpython.rlib.rarithmetic import r_uint, intmask
@specialize.argtype(1)
@@ -828,33 +829,37 @@
return s
# This part is slow.
negative = value < 0
- value = abs(value)
+ base = r_uint(base)
+ value = r_uint(value)
+ if negative: # change the sign on the unsigned number: otherwise,
+ value = -value # we'd risk overflow if value==-sys.maxint-1
+ #
buf = ["\0"] * (8 * 8 + 6) # Too much on 32 bit, but who cares?
i = len(buf) - 1
while True:
- div = value // base
- mod = value - div * base
- digit = abs(mod)
+ div = value // base # unsigned
+ mod = value - div * base # unsigned, always in range(0,base)
+ digit = intmask(mod)
digit += ord("0") if digit < 10 else ord("a") - 10
buf[i] = chr(digit)
- value = div
+ value = div # unsigned
i -= 1
if not value:
break
- if base == 2:
+ if base == r_uint(2):
buf[i] = "b"
buf[i - 1] = "0"
- elif base == 8:
+ elif base == r_uint(8):
buf[i] = "o"
buf[i - 1] = "0"
- elif base == 16:
+ elif base == r_uint(16):
buf[i] = "x"
buf[i - 1] = "0"
else:
buf[i] = "#"
- buf[i - 1] = chr(ord("0") + base % 10)
- if base > 10:
- buf[i - 2] = chr(ord("0") + base // 10)
+ buf[i - 1] = chr(ord("0") + intmask(base % r_uint(10)))
+ if base > r_uint(10):
+ buf[i - 2] = chr(ord("0") + intmask(base // r_uint(10)))
i -= 1
i -= 1
if negative:
diff --git a/pypy/tool/release/force-builds.py
b/pypy/tool/release/force-builds.py
--- a/pypy/tool/release/force-builds.py
+++ b/pypy/tool/release/force-builds.py
@@ -19,16 +19,16 @@
BUILDERS = [
'own-linux-x86-32',
'own-linux-x86-64',
- 'own-linux-armhf',
+# 'own-linux-armhf',
'own-win-x86-32',
- 'own-linux-s390x-2',
+ 'own-linux-s390x',
# 'own-macosx-x86-32',
'pypy-c-jit-linux-x86-32',
'pypy-c-jit-linux-x86-64',
# 'pypy-c-jit-freebsd-9-x86-64',
'pypy-c-jit-macosx-x86-64',
'pypy-c-jit-win-x86-32',
- 'pypy-c-jit-linux-s390x-2',
+ 'pypy-c-jit-linux-s390x',
'build-pypy-c-jit-linux-armhf-raring',
'build-pypy-c-jit-linux-armhf-raspbian',
'build-pypy-c-jit-linux-armel',
diff --git a/rpython/config/translationoption.py
b/rpython/config/translationoption.py
--- a/rpython/config/translationoption.py
+++ b/rpython/config/translationoption.py
@@ -213,11 +213,6 @@
default=False),
BoolOption("merge_if_blocks", "Merge if ... elif chains",
cmdline="--if-block-merge", default=True),
- BoolOption("raisingop2direct_call",
- "Transform operations that can implicitly raise an "
- "exception into calls to functions that explicitly "
- "raise exceptions",
- default=False, cmdline="--raisingop2direct_call"),
BoolOption("mallocs", "Remove mallocs", default=True),
BoolOption("constfold", "Constant propagation",
default=True),
diff --git a/rpython/jit/backend/arm/codebuilder.py
b/rpython/jit/backend/arm/codebuilder.py
--- a/rpython/jit/backend/arm/codebuilder.py
+++ b/rpython/jit/backend/arm/codebuilder.py
@@ -1,6 +1,5 @@
from rpython.jit.backend.arm import conditions as cond
from rpython.jit.backend.arm import registers as reg
-from rpython.jit.backend.arm import support
from rpython.jit.backend.arm.arch import WORD, PC_OFFSET
from rpython.jit.backend.arm.instruction_builder import define_instructions
from rpython.jit.backend.llsupport.asmmemmgr import BlockBuilderMixin
@@ -17,17 +16,6 @@
sandboxsafe=True)
-def binary_helper_call(name):
- function = getattr(support, 'arm_%s' % name)
-
- def f(self, c=cond.AL):
- """Generates a call to a helper function, takes its
- arguments in r0 and r1, result is placed in r0"""
- addr = rffi.cast(lltype.Signed, function)
- self.BL(addr, c)
- return f
-
-
class AbstractARMBuilder(object):
def __init__(self, arch_version=7):
self.arch_version = arch_version
@@ -348,10 +336,6 @@
self.write32(c << 28
| 0x157ff05f)
- DIV = binary_helper_call('int_div')
- MOD = binary_helper_call('int_mod')
- UDIV = binary_helper_call('uint_div')
-
FMDRR = VMOV_cr # uh, there are synonyms?
FMRRD = VMOV_rc
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
@@ -46,20 +46,6 @@
f.__name__ = 'emit_op_%s' % name
return f
-def gen_emit_op_by_helper_call(name, opname):
- helper = getattr(InstrBuilder, opname)
- def f(self, op, arglocs, regalloc, fcond):
- assert fcond is not None
- if op.type != 'v':
- regs = r.caller_resp[1:] + [r.ip]
- else:
- regs = r.caller_resp
- with saved_registers(self.mc, regs, r.caller_vfp_resp):
- helper(self.mc, fcond)
- return fcond
- f.__name__ = 'emit_op_%s' % name
- return f
-
def gen_emit_cmp_op(name, true_cond):
def f(self, op, arglocs, regalloc, fcond):
l0, l1, res = arglocs
diff --git a/rpython/jit/backend/arm/helper/regalloc.py
b/rpython/jit/backend/arm/helper/regalloc.py
--- a/rpython/jit/backend/arm/helper/regalloc.py
+++ b/rpython/jit/backend/arm/helper/regalloc.py
@@ -72,25 +72,6 @@
res = self.force_allocate_reg_or_cc(op)
return [loc1, loc2, res]
-def prepare_op_by_helper_call(name):
- def f(self, op, fcond):
- assert fcond is not None
- a0 = op.getarg(0)
- a1 = op.getarg(1)
- arg1 = self.rm.make_sure_var_in_reg(a0, selected_reg=r.r0)
- arg2 = self.rm.make_sure_var_in_reg(a1, selected_reg=r.r1)
- assert arg1 == r.r0
- assert arg2 == r.r1
- if not isinstance(a0, Const) and self.stays_alive(a0):
- self.force_spill_var(a0)
- self.possibly_free_vars_for_op(op)
- self.free_temp_vars()
- self.after_call(op)
- self.possibly_free_var(op)
- return []
- f.__name__ = name
- return f
-
def prepare_int_cmp(self, op, fcond):
assert fcond is not None
boxes = list(op.getarglist())
diff --git a/rpython/jit/backend/arm/opassembler.py
b/rpython/jit/backend/arm/opassembler.py
--- a/rpython/jit/backend/arm/opassembler.py
+++ b/rpython/jit/backend/arm/opassembler.py
@@ -3,7 +3,7 @@
from rpython.jit.backend.arm import registers as r
from rpython.jit.backend.arm import shift
from rpython.jit.backend.arm.arch import WORD, DOUBLE_WORD, JITFRAME_FIXED_SIZE
-from rpython.jit.backend.arm.helper.assembler import
(gen_emit_op_by_helper_call,
+from rpython.jit.backend.arm.helper.assembler import (
gen_emit_op_unary_cmp,
gen_emit_op_ri,
gen_emit_cmp_op,
@@ -92,6 +92,11 @@
self.mc.MUL(res.value, reg1.value, reg2.value)
return fcond
+ def emit_op_uint_mul_high(self, op, arglocs, regalloc, fcond):
+ reg1, reg2, res = arglocs
+ self.mc.UMULL(r.ip.value, res.value, reg1.value, reg2.value)
+ return fcond
+
def emit_op_int_force_ge_zero(self, op, arglocs, regalloc, fcond):
arg, res = arglocs
self.mc.CMP_ri(arg.value, 0)
@@ -132,10 +137,6 @@
self.guard_success_cc = c.VC
return fcond
- emit_op_int_floordiv = gen_emit_op_by_helper_call('int_floordiv', 'DIV')
- emit_op_int_mod = gen_emit_op_by_helper_call('int_mod', 'MOD')
- emit_op_uint_floordiv = gen_emit_op_by_helper_call('uint_floordiv', 'UDIV')
-
emit_op_int_and = gen_emit_op_ri('int_and', 'AND')
emit_op_int_or = gen_emit_op_ri('int_or', 'ORR')
emit_op_int_xor = gen_emit_op_ri('int_xor', 'EOR')
diff --git a/rpython/jit/backend/arm/regalloc.py
b/rpython/jit/backend/arm/regalloc.py
--- a/rpython/jit/backend/arm/regalloc.py
+++ b/rpython/jit/backend/arm/regalloc.py
@@ -7,7 +7,7 @@
from rpython.jit.backend.arm import conditions as c
from rpython.jit.backend.arm import locations
from rpython.jit.backend.arm.locations import imm, get_fp_offset
-from rpython.jit.backend.arm.helper.regalloc import (prepare_op_by_helper_call,
+from rpython.jit.backend.arm.helper.regalloc import (
prepare_unary_cmp,
prepare_op_ri,
prepare_int_cmp,
@@ -467,6 +467,8 @@
self.possibly_free_var(op)
return [reg1, reg2, res]
+ prepare_op_uint_mul_high = prepare_op_int_mul
+
def prepare_op_int_force_ge_zero(self, op, fcond):
argloc = self.make_sure_var_in_reg(op.getarg(0))
resloc = self.force_allocate_reg(op, [op.getarg(0)])
@@ -478,10 +480,6 @@
resloc = self.force_allocate_reg(op)
return [argloc, imm(numbytes), resloc]
- prepare_op_int_floordiv = prepare_op_by_helper_call('int_floordiv')
- prepare_op_int_mod = prepare_op_by_helper_call('int_mod')
- prepare_op_uint_floordiv = prepare_op_by_helper_call('unit_floordiv')
-
prepare_op_int_and = prepare_op_ri('int_and')
prepare_op_int_or = prepare_op_ri('int_or')
prepare_op_int_xor = prepare_op_ri('int_xor')
diff --git a/rpython/jit/backend/arm/support.py
b/rpython/jit/backend/arm/support.py
deleted file mode 100644
--- a/rpython/jit/backend/arm/support.py
+++ /dev/null
@@ -1,54 +0,0 @@
-from rpython.rtyper.lltypesystem import lltype, rffi, llmemory
-from rpython.rlib.rarithmetic import r_uint
-from rpython.translator.tool.cbuild import ExternalCompilationInfo
-
-eci = ExternalCompilationInfo(post_include_bits=["""
-static int pypy__arm_int_div(int a, int b) {
- return a/b;
-}
-static unsigned int pypy__arm_uint_div(unsigned int a, unsigned int b) {
- return a/b;
-}
-static int pypy__arm_int_mod(int a, int b) {
- return a % b;
-}
-"""])
-
-
-def arm_int_div_emulator(a, b):
- return int(a / float(b))
-arm_int_div_sign = lltype.Ptr(
- lltype.FuncType([lltype.Signed, lltype.Signed], lltype.Signed))
-arm_int_div = rffi.llexternal(
- "pypy__arm_int_div", [lltype.Signed, lltype.Signed], lltype.Signed,
- _callable=arm_int_div_emulator,
- compilation_info=eci,
- _nowrapper=True, elidable_function=True)
-
-
-def arm_uint_div_emulator(a, b):
- return r_uint(a) / r_uint(b)
-arm_uint_div_sign = lltype.Ptr(
- lltype.FuncType([lltype.Unsigned, lltype.Unsigned], lltype.Unsigned))
-arm_uint_div = rffi.llexternal(
- "pypy__arm_uint_div", [lltype.Unsigned, lltype.Unsigned], lltype.Unsigned,
- _callable=arm_uint_div_emulator,
- compilation_info=eci,
- _nowrapper=True, elidable_function=True)
-
-
-def arm_int_mod_emulator(a, b):
- sign = 1
- if a < 0:
- a = -1 * a
- sign = -1
- if b < 0:
- b = -1 * b
- res = a % b
- return sign * res
-arm_int_mod_sign = arm_int_div_sign
-arm_int_mod = rffi.llexternal(
- "pypy__arm_int_mod", [lltype.Signed, lltype.Signed], lltype.Signed,
- _callable=arm_int_mod_emulator,
- compilation_info=eci,
- _nowrapper=True, elidable_function=True)
diff --git a/rpython/jit/backend/arm/test/test_arch.py
b/rpython/jit/backend/arm/test/test_arch.py
deleted file mode 100644
--- a/rpython/jit/backend/arm/test/test_arch.py
+++ /dev/null
@@ -1,23 +0,0 @@
-from rpython.jit.backend.arm import support
-
-def test_mod():
- assert support.arm_int_mod(10, 2) == 0
- assert support.arm_int_mod(11, 2) == 1
- assert support.arm_int_mod(11, 3) == 2
-
-def test_mod2():
- assert support.arm_int_mod(-10, 2) == 0
- assert support.arm_int_mod(-11, 2) == -1
- assert support.arm_int_mod(-11, 3) == -2
-
-def test_mod3():
- assert support.arm_int_mod(10, -2) == 0
- assert support.arm_int_mod(11, -2) == 1
- assert support.arm_int_mod(11, -3) == 2
-
-
-def test_div():
- assert support.arm_int_div(-7, 2) == -3
- assert support.arm_int_div(9, 2) == 4
- assert support.arm_int_div(10, 5) == 2
-
diff --git a/rpython/jit/backend/arm/test/test_assembler.py
b/rpython/jit/backend/arm/test/test_assembler.py
--- a/rpython/jit/backend/arm/test/test_assembler.py
+++ b/rpython/jit/backend/arm/test/test_assembler.py
@@ -193,32 +193,6 @@
self.a.gen_func_epilog()
assert run_asm(self.a) == 61
- def test_DIV(self):
- self.a.gen_func_prolog()
- self.a.mc.MOV_ri(r.r0.value, 123)
- self.a.mc.MOV_ri(r.r1.value, 2)
- self.a.mc.DIV()
- self.a.gen_func_epilog()
- assert run_asm(self.a) == 61
-
- def test_DIV2(self):
- self.a.gen_func_prolog()
- self.a.mc.gen_load_int(r.r0.value, -110)
- self.a.mc.gen_load_int(r.r1.value, 3)
- self.a.mc.DIV()
- self.a.gen_func_epilog()
- assert run_asm(self.a) == -36
-
- def test_DIV3(self):
- self.a.gen_func_prolog()
- self.a.mc.gen_load_int(r.r8.value, 110)
- self.a.mc.gen_load_int(r.r9.value, -3)
- self.a.mc.MOV_rr(r.r0.value, r.r8.value)
- self.a.mc.MOV_rr(r.r1.value, r.r9.value)
- self.a.mc.DIV()
- self.a.gen_func_epilog()
- assert run_asm(self.a) == -36
-
def test_bl_with_conditional_exec(self):
functype = lltype.Ptr(lltype.FuncType([lltype.Signed], lltype.Signed))
call_addr = rffi.cast(lltype.Signed, llhelper(functype, callme))
diff --git a/rpython/jit/backend/llsupport/test/test_regalloc_integration.py
b/rpython/jit/backend/llsupport/test/test_regalloc_integration.py
--- a/rpython/jit/backend/llsupport/test/test_regalloc_integration.py
+++ b/rpython/jit/backend/llsupport/test/test_regalloc_integration.py
@@ -496,22 +496,6 @@
self.interpret(ops, [s, ord('a')])
assert s[1] == 'a'
- def test_division_optimized(self):
- ops = '''
- [i7, i6]
- label(i7, i6, descr=targettoken)
- i18 = int_floordiv(i7, i6)
- i19 = int_xor(i7, i6)
- i21 = int_lt(i19, 0)
- i22 = int_mod(i7, i6)
- i23 = int_is_true(i22)
- i24 = int_eq(i6, 4)
- guard_false(i24) [i18]
- jump(i18, i6, descr=targettoken)
- '''
- self.interpret(ops, [10, 4])
- assert self.getint(0) == 2
- # FIXME: Verify that i19 - i23 are removed
class TestRegallocFloats(BaseTestRegalloc):
def setup_class(cls):
diff --git a/rpython/jit/backend/ppc/opassembler.py
b/rpython/jit/backend/ppc/opassembler.py
--- a/rpython/jit/backend/ppc/opassembler.py
+++ b/rpython/jit/backend/ppc/opassembler.py
@@ -62,6 +62,12 @@
else:
self.mc.mulld(res.value, l0.value, l1.value)
+ def emit_uint_mul_high(self, op, arglocs, regalloc):
+ l0, l1, res = arglocs
+ assert not l0.is_imm()
+ assert not l1.is_imm()
+ self.mc.mulhdu(res.value, l0.value, l1.value)
+
def do_emit_int_binary_ovf(self, op, arglocs):
l0, l1, res = arglocs[0], arglocs[1], arglocs[2]
self.mc.load_imm(r.SCRATCH, 0)
@@ -80,24 +86,6 @@
else:
self.mc.mulldox(*self.do_emit_int_binary_ovf(op, arglocs))
- def emit_int_floordiv(self, op, arglocs, regalloc):
- l0, l1, res = arglocs
- if IS_PPC_32:
- self.mc.divw(res.value, l0.value, l1.value)
- else:
- self.mc.divd(res.value, l0.value, l1.value)
-
- def emit_int_mod(self, op, arglocs, regalloc):
- l0, l1, res = arglocs
- if IS_PPC_32:
- self.mc.divw(r.r0.value, l0.value, l1.value)
- self.mc.mullw(r.r0.value, r.r0.value, l1.value)
- else:
- self.mc.divd(r.r0.value, l0.value, l1.value)
- self.mc.mulld(r.r0.value, r.r0.value, l1.value)
- self.mc.subf(r.r0.value, r.r0.value, l0.value)
- self.mc.mr(res.value, r.r0.value)
-
def emit_int_and(self, op, arglocs, regalloc):
l0, l1, res = arglocs
self.mc.and_(res.value, l0.value, l1.value)
@@ -130,13 +118,6 @@
self.mc.srw(res.value, l0.value, l1.value)
else:
self.mc.srd(res.value, l0.value, l1.value)
-
- def emit_uint_floordiv(self, op, arglocs, regalloc):
- l0, l1, res = arglocs
- if IS_PPC_32:
- self.mc.divwu(res.value, l0.value, l1.value)
- else:
- self.mc.divdu(res.value, l0.value, l1.value)
emit_int_le = gen_emit_cmp_op(c.LE)
emit_int_lt = gen_emit_cmp_op(c.LT)
diff --git a/rpython/jit/backend/ppc/regalloc.py
b/rpython/jit/backend/ppc/regalloc.py
--- a/rpython/jit/backend/ppc/regalloc.py
+++ b/rpython/jit/backend/ppc/regalloc.py
@@ -432,15 +432,13 @@
prepare_int_mul = helper.prepare_int_add_or_mul
prepare_nursery_ptr_increment = prepare_int_add
- prepare_int_floordiv = helper.prepare_binary_op
- prepare_int_mod = helper.prepare_binary_op
prepare_int_and = helper.prepare_binary_op
prepare_int_or = helper.prepare_binary_op
prepare_int_xor = helper.prepare_binary_op
prepare_int_lshift = helper.prepare_binary_op
prepare_int_rshift = helper.prepare_binary_op
prepare_uint_rshift = helper.prepare_binary_op
- prepare_uint_floordiv = helper.prepare_binary_op
+ prepare_uint_mul_high = helper.prepare_binary_op
prepare_int_add_ovf = helper.prepare_binary_op
prepare_int_sub_ovf = helper.prepare_binary_op
diff --git a/rpython/jit/backend/test/test_random.py
b/rpython/jit/backend/test/test_random.py
--- a/rpython/jit/backend/test/test_random.py
+++ b/rpython/jit/backend/test/test_random.py
@@ -532,6 +532,7 @@
rop.INT_AND,
rop.INT_OR,
rop.INT_XOR,
+ rop.UINT_MUL_HIGH,
]:
OPERATIONS.append(BinaryOperation(_op))
@@ -548,8 +549,8 @@
]:
OPERATIONS.append(BinaryOperation(_op, boolres=True))
-OPERATIONS.append(BinaryOperation(rop.INT_FLOORDIV, ~3, 2))
-OPERATIONS.append(BinaryOperation(rop.INT_MOD, ~3, 2))
+#OPERATIONS.append(BinaryOperation(rop.INT_FLOORDIV, ~3, 2))
+#OPERATIONS.append(BinaryOperation(rop.INT_MOD, ~3, 2))
OPERATIONS.append(BinaryOperation(rop.INT_RSHIFT, LONG_BIT-1))
OPERATIONS.append(BinaryOperation(rop.INT_LSHIFT, LONG_BIT-1))
OPERATIONS.append(BinaryOperation(rop.UINT_RSHIFT, LONG_BIT-1))
diff --git a/rpython/jit/backend/x86/assembler.py
b/rpython/jit/backend/x86/assembler.py
--- a/rpython/jit/backend/x86/assembler.py
+++ b/rpython/jit/backend/x86/assembler.py
@@ -1289,6 +1289,9 @@
genop_float_mul = _binaryop('MULSD')
genop_float_truediv = _binaryop('DIVSD')
+ def genop_uint_mul_high(self, op, arglocs, result_loc):
+ self.mc.MUL(arglocs[0])
+
def genop_int_and(self, op, arglocs, result_loc):
arg1 = arglocs[1]
if IS_X86_64 and (isinstance(arg1, ImmedLoc) and
@@ -1444,20 +1447,6 @@
self.mov(imm0, resloc)
self.mc.CMOVNS(resloc, arglocs[0])
- def genop_int_mod(self, op, arglocs, resloc):
- if IS_X86_32:
- self.mc.CDQ()
- elif IS_X86_64:
- self.mc.CQO()
-
- self.mc.IDIV_r(ecx.value)
-
- genop_int_floordiv = genop_int_mod
-
- def genop_uint_floordiv(self, op, arglocs, resloc):
- self.mc.XOR_rr(edx.value, edx.value)
- self.mc.DIV_r(ecx.value)
-
genop_llong_add = _binaryop("PADDQ")
genop_llong_sub = _binaryop("PSUBQ")
genop_llong_and = _binaryop("PAND")
diff --git a/rpython/jit/backend/x86/regalloc.py
b/rpython/jit/backend/x86/regalloc.py
--- a/rpython/jit/backend/x86/regalloc.py
+++ b/rpython/jit/backend/x86/regalloc.py
@@ -561,6 +561,27 @@
consider_int_sub_ovf = _consider_binop
consider_int_add_ovf = _consider_binop_symm
+ def consider_uint_mul_high(self, op):
+ arg1, arg2 = op.getarglist()
+ # should support all cases, but is optimized for (box, const)
+ if isinstance(arg1, Const):
+ arg1, arg2 = arg2, arg1
+ self.rm.make_sure_var_in_reg(arg2, selected_reg=eax)
+ l1 = self.loc(arg1)
+ # l1 is a register != eax, or stack_bp; or, just possibly, it
+ # can be == eax if arg1 is arg2
+ assert not isinstance(l1, ImmedLoc)
+ assert l1 is not eax or arg1 is arg2
+ #
+ # eax will be trash after the operation
+ self.rm.possibly_free_var(arg2)
+ tmpvar = TempVar()
+ self.rm.force_allocate_reg(tmpvar, selected_reg=eax)
+ self.rm.possibly_free_var(tmpvar)
+ #
+ self.rm.force_allocate_reg(op, selected_reg=edx)
+ self.perform(op, [l1], edx)
+
def consider_int_neg(self, op):
res = self.rm.force_result_in_reg(op, op.getarg(0))
self.perform(op, [res], res)
@@ -585,29 +606,6 @@
consider_int_rshift = consider_int_lshift
consider_uint_rshift = consider_int_lshift
- def _consider_int_div_or_mod(self, op, resultreg, trashreg):
- l0 = self.rm.make_sure_var_in_reg(op.getarg(0), selected_reg=eax)
- l1 = self.rm.make_sure_var_in_reg(op.getarg(1), selected_reg=ecx)
- l2 = self.rm.force_allocate_reg(op, selected_reg=resultreg)
- # the register (eax or edx) not holding what we are looking for
- # will be just trash after that operation
- tmpvar = TempVar()
- self.rm.force_allocate_reg(tmpvar, selected_reg=trashreg)
- assert l0 is eax
- assert l1 is ecx
- assert l2 is resultreg
- self.rm.possibly_free_var(tmpvar)
-
- def consider_int_mod(self, op):
- self._consider_int_div_or_mod(op, edx, eax)
- self.perform(op, [eax, ecx], edx)
-
- def consider_int_floordiv(self, op):
- self._consider_int_div_or_mod(op, eax, edx)
- self.perform(op, [eax, ecx], eax)
-
- consider_uint_floordiv = consider_int_floordiv
-
def _consider_compop(self, op):
vx = op.getarg(0)
vy = op.getarg(1)
diff --git a/rpython/jit/backend/x86/regloc.py
b/rpython/jit/backend/x86/regloc.py
--- a/rpython/jit/backend/x86/regloc.py
+++ b/rpython/jit/backend/x86/regloc.py
@@ -641,6 +641,7 @@
SUB = _binaryop('SUB')
IMUL = _binaryop('IMUL')
NEG = _unaryop('NEG')
+ MUL = _unaryop('MUL')
CMP = _binaryop('CMP')
CMP16 = _binaryop('CMP16')
diff --git a/rpython/jit/backend/x86/rx86.py b/rpython/jit/backend/x86/rx86.py
--- a/rpython/jit/backend/x86/rx86.py
+++ b/rpython/jit/backend/x86/rx86.py
@@ -558,6 +558,9 @@
DIV_r = insn(rex_w, '\xF7', register(1), '\xF0')
IDIV_r = insn(rex_w, '\xF7', register(1), '\xF8')
+ MUL_r = insn(rex_w, '\xF7', orbyte(4<<3), register(1), '\xC0')
+ MUL_b = insn(rex_w, '\xF7', orbyte(4<<3), stack_bp(1))
+
IMUL_rr = insn(rex_w, '\x0F\xAF', register(1, 8), register(2), '\xC0')
IMUL_rb = insn(rex_w, '\x0F\xAF', register(1, 8), stack_bp(2))
diff --git a/rpython/jit/codewriter/effectinfo.py
b/rpython/jit/codewriter/effectinfo.py
--- a/rpython/jit/codewriter/effectinfo.py
+++ b/rpython/jit/codewriter/effectinfo.py
@@ -28,6 +28,11 @@
OS_THREADLOCALREF_GET = 5 # llop.threadlocalref_get
OS_NOT_IN_TRACE = 8 # for calls not recorded in the jit
trace
#
+ OS_INT_PY_DIV = 12 # python signed division (neg.
corrected)
+ OS_INT_UDIV = 13 # regular unsigned division
+ OS_INT_PY_MOD = 14 # python signed modulo (neg. corrected)
+ OS_INT_UMOD = 15 # regular unsigned modulo
+ #
OS_STR_CONCAT = 22 # "stroruni.concat"
OS_STR_SLICE = 23 # "stroruni.slice"
OS_STR_EQUAL = 24 # "stroruni.equal"
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
@@ -436,6 +436,8 @@
# dispatch to various implementations depending on the oopspec_name
if oopspec_name.startswith('list.') or
oopspec_name.startswith('newlist'):
prepare = self._handle_list_call
+ elif oopspec_name.startswith('int.'):
+ prepare = self._handle_int_special
elif oopspec_name.startswith('stroruni.'):
prepare = self._handle_stroruni_call
elif oopspec_name == 'str.str2unicode':
@@ -518,23 +520,12 @@
# XXX some of the following functions should not become residual calls
# but be really compiled
- rewrite_op_int_floordiv_ovf_zer = _do_builtin_call
- rewrite_op_int_floordiv_ovf = _do_builtin_call
- rewrite_op_int_floordiv_zer = _do_builtin_call
- rewrite_op_int_mod_ovf_zer = _do_builtin_call
- rewrite_op_int_mod_ovf = _do_builtin_call
- rewrite_op_int_mod_zer = _do_builtin_call
- rewrite_op_int_lshift_ovf = _do_builtin_call
rewrite_op_int_abs = _do_builtin_call
rewrite_op_llong_abs = _do_builtin_call
rewrite_op_llong_floordiv = _do_builtin_call
- rewrite_op_llong_floordiv_zer = _do_builtin_call
rewrite_op_llong_mod = _do_builtin_call
- rewrite_op_llong_mod_zer = _do_builtin_call
rewrite_op_ullong_floordiv = _do_builtin_call
- rewrite_op_ullong_floordiv_zer = _do_builtin_call
rewrite_op_ullong_mod = _do_builtin_call
- rewrite_op_ullong_mod_zer = _do_builtin_call
rewrite_op_gc_identityhash = _do_builtin_call
rewrite_op_gc_id = _do_builtin_call
rewrite_op_gc_pin = _do_builtin_call
@@ -1532,12 +1523,6 @@
return self.rewrite_operation(op1)
''' % (_old, _new)).compile()
- def rewrite_op_int_neg_ovf(self, op):
- op1 = SpaceOperation('int_sub_ovf',
- [Constant(0, lltype.Signed), op.args[0]],
- op.result)
- return self.rewrite_operation(op1)
-
def rewrite_op_float_is_true(self, op):
op1 = SpaceOperation('float_ne',
[op.args[0], Constant(0.0, lltype.Float)],
@@ -1929,6 +1914,20 @@
llmemory.cast_ptr_to_adr(c_func.value))
self.callcontrol.callinfocollection.add(oopspecindex, calldescr, func)
+ def _handle_int_special(self, op, oopspec_name, args):
+ if oopspec_name == 'int.neg_ovf':
+ [v_x] = args
+ op0 = SpaceOperation('int_sub_ovf',
+ [Constant(0, lltype.Signed), v_x],
+ op.result)
+ return self.rewrite_operation(op0)
+ else:
+ # int.py_div, int.udiv, int.py_mod, int.umod
+ opname = oopspec_name.replace('.', '_')
+ os = getattr(EffectInfo, 'OS_' + opname.upper())
+ return self._handle_oopspec_call(op, args, os,
+ EffectInfo.EF_ELIDABLE_CANNOT_RAISE)
+
def _handle_stroruni_call(self, op, oopspec_name, args):
SoU = args[0].concretetype # Ptr(STR) or Ptr(UNICODE)
can_raise_memoryerror = {
diff --git a/rpython/jit/codewriter/support.py
b/rpython/jit/codewriter/support.py
--- a/rpython/jit/codewriter/support.py
+++ b/rpython/jit/codewriter/support.py
@@ -243,45 +243,6 @@
return llop.jit_force_virtual(lltype.typeOf(inst), inst)
-def _ll_2_int_floordiv_ovf_zer(x, y):
- if y == 0:
- raise ZeroDivisionError
- return _ll_2_int_floordiv_ovf(x, y)
-
-def _ll_2_int_floordiv_ovf(x, y):
- # intentionally not short-circuited to produce only one guard
- # and to remove the check fully if one of the arguments is known
- if (x == -sys.maxint - 1) & (y == -1):
- raise OverflowError
- return llop.int_floordiv(lltype.Signed, x, y)
-
-def _ll_2_int_floordiv_zer(x, y):
- if y == 0:
- raise ZeroDivisionError
- return llop.int_floordiv(lltype.Signed, x, y)
-
-def _ll_2_int_mod_ovf_zer(x, y):
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit