[pypy-commit] pypy cpyext-ext: merge default into branch
mattip
pypy.commits at gmail.com
Wed Dec 23 17:24:35 EST 2015
Author: mattip <matti.picus at gmail.com>
Branch: cpyext-ext
Changeset: r81440:d3063a8c955b
Date: 2015-12-24 00:23 +0200
http://bitbucket.org/pypy/pypy/changeset/d3063a8c955b/
Log: merge default into branch
diff too long, truncating to 2000 out of 13951 lines
diff --git a/.gitignore b/.gitignore
--- a/.gitignore
+++ b/.gitignore
@@ -29,4 +29,4 @@
release/
!pypy/tool/release/
rpython/_cache/
-__pycache__/
+.cache/
diff --git a/lib_pypy/cffi.egg-info/PKG-INFO b/lib_pypy/cffi.egg-info/PKG-INFO
--- a/lib_pypy/cffi.egg-info/PKG-INFO
+++ b/lib_pypy/cffi.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: cffi
-Version: 1.3.1
+Version: 1.4.1
Summary: Foreign Function Interface for Python calling C code.
Home-page: http://cffi.readthedocs.org
Author: Armin Rigo, Maciej Fijalkowski
diff --git a/lib_pypy/cffi/__init__.py b/lib_pypy/cffi/__init__.py
--- a/lib_pypy/cffi/__init__.py
+++ b/lib_pypy/cffi/__init__.py
@@ -4,8 +4,8 @@
from .api import FFI, CDefError, FFIError
from .ffiplatform import VerificationError, VerificationMissing
-__version__ = "1.3.1"
-__version_info__ = (1, 3, 1)
+__version__ = "1.4.1"
+__version_info__ = (1, 4, 1)
# The verifier module file names are based on the CRC32 of a string that
# contains the following version number. It may be older than __version__
diff --git a/lib_pypy/cffi/api.py b/lib_pypy/cffi/api.py
--- a/lib_pypy/cffi/api.py
+++ b/lib_pypy/cffi/api.py
@@ -73,6 +73,7 @@
self._included_ffis = []
self._windows_unicode = None
self._init_once_cache = {}
+ self._cdef_version = None
if hasattr(backend, 'set_ffi'):
backend.set_ffi(self)
for name in backend.__dict__:
@@ -105,6 +106,7 @@
raise TypeError("cdef() argument must be a string")
csource = csource.encode('ascii')
with self._lock:
+ self._cdef_version = object()
self._parser.parse(csource, override=override, packed=packed)
self._cdefsources.append(csource)
if override:
@@ -646,70 +648,70 @@
import os
backend = ffi._backend
backendlib = _load_backend_lib(backend, libname, flags)
- copied_enums = []
#
- def make_accessor_locked(name):
+ def accessor_function(name):
key = 'function ' + name
- if key in ffi._parser._declarations:
- tp, _ = ffi._parser._declarations[key]
- BType = ffi._get_cached_btype(tp)
- try:
- value = backendlib.load_function(BType, name)
- except KeyError as e:
- raise AttributeError('%s: %s' % (name, e))
- library.__dict__[name] = value
+ tp, _ = ffi._parser._declarations[key]
+ BType = ffi._get_cached_btype(tp)
+ try:
+ value = backendlib.load_function(BType, name)
+ except KeyError as e:
+ raise AttributeError('%s: %s' % (name, e))
+ library.__dict__[name] = value
+ #
+ def accessor_variable(name):
+ key = 'variable ' + name
+ tp, _ = ffi._parser._declarations[key]
+ BType = ffi._get_cached_btype(tp)
+ read_variable = backendlib.read_variable
+ write_variable = backendlib.write_variable
+ setattr(FFILibrary, name, property(
+ lambda self: read_variable(BType, name),
+ lambda self, value: write_variable(BType, name, value)))
+ #
+ def accessor_constant(name):
+ raise NotImplementedError("non-integer constant '%s' cannot be "
+ "accessed from a dlopen() library" % (name,))
+ #
+ def accessor_int_constant(name):
+ library.__dict__[name] = ffi._parser._int_constants[name]
+ #
+ accessors = {}
+ accessors_version = [False]
+ #
+ def update_accessors():
+ if accessors_version[0] is ffi._cdef_version:
return
#
- key = 'variable ' + name
- if key in ffi._parser._declarations:
- tp, _ = ffi._parser._declarations[key]
- BType = ffi._get_cached_btype(tp)
- read_variable = backendlib.read_variable
- write_variable = backendlib.write_variable
- setattr(FFILibrary, name, property(
- lambda self: read_variable(BType, name),
- lambda self, value: write_variable(BType, name, value)))
- return
- #
- if not copied_enums:
- from . import model
- error = None
- for key, (tp, _) in ffi._parser._declarations.items():
- if not isinstance(tp, model.EnumType):
- continue
- try:
- tp.check_not_partial()
- except Exception as e:
- error = e
- continue
- for enumname, enumval in zip(tp.enumerators, tp.enumvalues):
- if enumname not in library.__dict__:
- library.__dict__[enumname] = enumval
- if error is not None:
- if name in library.__dict__:
- return # ignore error, about a different enum
- raise error
-
- for key, val in ffi._parser._int_constants.items():
- if key not in library.__dict__:
- library.__dict__[key] = val
-
- copied_enums.append(True)
- if name in library.__dict__:
- return
- #
- key = 'constant ' + name
- if key in ffi._parser._declarations:
- raise NotImplementedError("fetching a non-integer constant "
- "after dlopen()")
- #
- raise AttributeError(name)
+ from . import model
+ for key, (tp, _) in ffi._parser._declarations.items():
+ if not isinstance(tp, model.EnumType):
+ tag, name = key.split(' ', 1)
+ if tag == 'function':
+ accessors[name] = accessor_function
+ elif tag == 'variable':
+ accessors[name] = accessor_variable
+ elif tag == 'constant':
+ accessors[name] = accessor_constant
+ else:
+ for i, enumname in enumerate(tp.enumerators):
+ def accessor_enum(name, tp=tp, i=i):
+ tp.check_not_partial()
+ library.__dict__[name] = tp.enumvalues[i]
+ accessors[enumname] = accessor_enum
+ for name in ffi._parser._int_constants:
+ accessors.setdefault(name, accessor_int_constant)
+ accessors_version[0] = ffi._cdef_version
#
def make_accessor(name):
with ffi._lock:
if name in library.__dict__ or name in FFILibrary.__dict__:
return # added by another thread while waiting for the lock
- make_accessor_locked(name)
+ if name not in accessors:
+ update_accessors()
+ if name not in accessors:
+ raise AttributeError(name)
+ accessors[name](name)
#
class FFILibrary(object):
def __getattr__(self, name):
@@ -723,6 +725,10 @@
setattr(self, name, value)
else:
property.__set__(self, value)
+ def __dir__(self):
+ with ffi._lock:
+ update_accessors()
+ return accessors.keys()
#
if libname is not None:
try:
diff --git a/pypy/doc/build.rst b/pypy/doc/build.rst
--- a/pypy/doc/build.rst
+++ b/pypy/doc/build.rst
@@ -73,28 +73,36 @@
lzma (PyPy3 only)
liblzma
-sqlite3
- libsqlite3
-
-curses
- libncurses + cffi dependencies from above
-
pyexpat
libexpat1
_ssl
libssl
+Make sure to have these libraries (with development headers) installed
+before building PyPy, otherwise the resulting binary will not contain
+these modules. Furthermore, the following libraries should be present
+after building PyPy, otherwise the corresponding CFFI modules are not
+built (you can run or re-run `pypy/tool/release/package.py` to retry
+to build them; you don't need to re-translate the whole PyPy):
+
+sqlite3
+ libsqlite3
+
+curses
+ libncurses
+
gdbm
libgdbm-dev
-Make sure to have these libraries (with development headers) installed before
-building PyPy, otherwise the resulting binary will not contain these modules.
+tk
+ tk-dev
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
+ libsqlite3-dev libncurses-dev libexpat1-dev libssl-dev libgdbm-dev \
+ tk-dev
For the optional lzma module on PyPy3 you will also need ``liblzma-dev``.
@@ -102,6 +110,7 @@
yum install gcc make libffi-devel pkgconfig zlib-devel bzip2-devel \
lib-sqlite3-devel ncurses-devel expat-devel openssl-devel
+ (XXX plus the Febora version of libgdbm-dev and tk-dev)
For the optional lzma module on PyPy3 you will also need ``xz-devel``.
@@ -110,6 +119,7 @@
zypper install gcc make python-devel pkg-config \
zlib-devel libopenssl-devel libbz2-devel sqlite3-devel \
libexpat-devel libffi-devel python-curses
+ (XXX plus the SLES11 version of libgdbm-dev and tk-dev)
For the optional lzma module on PyPy3 you will also need ``xz-devel``.
@@ -125,11 +135,13 @@
Translate with JIT::
- pypy rpython/bin/rpython --opt=jit pypy/goal/targetpypystandalone.py
+ cd pypy/goal
+ pypy ../../rpython/bin/rpython --opt=jit
Translate without JIT::
- pypy rpython/bin/rpython --opt=2 pypy/goal/targetpypystandalone.py
+ cd pypy/goal
+ pypy ../../rpython/bin/rpython --opt=2
(You can use ``python`` instead of ``pypy`` here, which will take longer
but works too.)
diff --git a/pypy/doc/embedding.rst b/pypy/doc/embedding.rst
--- a/pypy/doc/embedding.rst
+++ b/pypy/doc/embedding.rst
@@ -130,8 +130,13 @@
More complete example
---------------------
-.. note:: This example depends on pypy_execute_source_ptr which is not available
- in PyPy <= 2.2.1.
+.. note:: Note that we do not make use of ``extern "Python"``, the new
+ way to do callbacks in CFFI 1.4: this is because these examples use
+ the ABI mode, not the API mode, and with the ABI mode you still have
+ to use ``ffi.callback()``. It is work in progress to integrate
+ ``extern "Python"`` with the idea of embedding (and it is expected
+ to ultimately lead to a better way to do embedding than the one
+ described here, and that would work equally well on CPython and PyPy).
Typically we need something more to do than simply execute source. The following
is a fully fledged example, please consult cffi documentation for details.
diff --git a/pypy/doc/stm.rst b/pypy/doc/stm.rst
--- a/pypy/doc/stm.rst
+++ b/pypy/doc/stm.rst
@@ -83,29 +83,27 @@
**pypy-stm requires 64-bit Linux for now.**
-Development is done in the branch `stmgc-c7`_. If you are only
-interested in trying it out, you can download a Ubuntu binary here__
-(``pypy-stm-2.*.tar.bz2``, for Ubuntu 12.04-14.04). The current version
-supports four "segments", which means that it will run up to four
-threads in parallel. (Development recently switched to `stmgc-c8`_,
-but that is not ready for trying out yet.)
+Development is done in the branch `stmgc-c8`_. If you are only
+interested in trying it out, please pester us until we upload a recent
+prebuilt binary. The current version supports four "segments", which
+means that it will run up to four threads in parallel.
To build a version from sources, you first need to compile a custom
-version of clang(!); we recommend downloading `llvm and clang like
-described here`__, but at revision 201645 (use ``svn co -r 201645 <path>``
-for all checkouts). Then apply all the patches in `this directory`__:
-they are fixes for a clang-only feature that hasn't been used so heavily
-in the past (without the patches, you get crashes of clang). Then get
-the branch `stmgc-c7`_ of PyPy and run::
+version of gcc(!). See the instructions here:
+https://bitbucket.org/pypy/stmgc/src/default/gcc-seg-gs/
+(Note that these patches are being incorporated into gcc. It is likely
+that future versions of gcc will not need to be patched any more.)
- rpython/bin/rpython -Ojit --stm pypy/goal/targetpypystandalone.py
- PYTHONPATH=. ./pypy-c pypy/tool/build_cffi_imports.py
+Then get the branch `stmgc-c8`_ of PyPy and run::
-.. _`stmgc-c7`: https://bitbucket.org/pypy/pypy/src/stmgc-c7/
+ cd pypy/goal
+ ../../rpython/bin/rpython -Ojit --stm
+
+At the end, this will try to compile the generated C code by calling
+``gcc-seg-gs``, which must be the script you installed in the
+instructions above.
+
.. _`stmgc-c8`: https://bitbucket.org/pypy/pypy/src/stmgc-c8/
-.. __: https://bitbucket.org/pypy/pypy/downloads/
-.. __: http://clang.llvm.org/get_started.html
-.. __: https://bitbucket.org/pypy/stmgc/src/default/c7/llvmfix/
.. _caveats:
@@ -113,6 +111,12 @@
Current status (stmgc-c7)
-------------------------
+.. warning::
+
+ THIS PAGE IS OLD, THE REST IS ABOUT STMGC-C7 WHEREAS THE CURRENT
+ DEVELOPMENT WORK IS DONE ON STMGC-C8
+
+
* **NEW:** It seems to work fine, without crashing any more. Please `report
any crash`_ you find (or other bugs).
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
@@ -44,6 +44,9 @@
.. branch: fix-setslice-can-resize
+Make rlist's ll_listsetslice() able to resize the target list to help
+simplify objspace/std/listobject.py. Was issue #2196.
+
.. branch: anntype2
A somewhat random bunch of changes and fixes following up on branch 'anntype'. Highlights:
@@ -61,3 +64,40 @@
.. branch: vecopt-absvalue
- Enhancement. Removed vector fields from AbstractValue.
+
+.. branch: memop-simplify2
+
+Simplification. Backends implement too many loading instructions, only having a slightly different interface.
+Four new operations (gc_load/gc_load_indexed, gc_store/gc_store_indexed) replace all the
+commonly known loading operations
+
+.. branch: more-rposix
+
+Move wrappers for OS functions from `rpython/rtyper` to `rpython/rlib` and
+turn them into regular RPython functions. Most RPython-compatible `os.*`
+functions are now directly accessible as `rpython.rposix.*`.
+
+.. branch: always-enable-gil
+
+Simplify a bit the GIL handling in non-jitted code. Fixes issue #2205.
+
+.. branch: flowspace-cleanups
+
+Trivial cleanups in flowspace.operation : fix comment & duplicated method
+
+.. branch: test-AF_NETLINK
+
+Add a test for pre-existing AF_NETLINK support. Was part of issue #1942.
+
+.. branch: small-cleanups-misc
+
+Trivial misc cleanups: typo, whitespace, obsolete comments
+
+.. branch: cpyext-slotdefs
+.. branch: fix-missing-canraise
+.. branch: whatsnew
+
+.. branch: fix-2211
+
+Fix the cryptic exception message when attempting to use extended slicing
+in rpython. Was issue #2211.
diff --git a/pypy/interpreter/astcompiler/assemble.py b/pypy/interpreter/astcompiler/assemble.py
--- a/pypy/interpreter/astcompiler/assemble.py
+++ b/pypy/interpreter/astcompiler/assemble.py
@@ -289,6 +289,8 @@
for w_item in space.fixedview(obj):
result_w.append(self._make_key(w_item))
w_key = space.newtuple(result_w[:])
+ elif isinstance(obj, PyCode):
+ w_key = space.newtuple([obj, w_type, space.id(obj)])
else:
w_key = space.newtuple([obj, w_type])
return w_key
diff --git a/pypy/interpreter/astcompiler/test/test_compiler.py b/pypy/interpreter/astcompiler/test/test_compiler.py
--- a/pypy/interpreter/astcompiler/test/test_compiler.py
+++ b/pypy/interpreter/astcompiler/test/test_compiler.py
@@ -931,6 +931,11 @@
finally:
space.call_function(w_set_debug, space.w_True)
+ def test_dont_fold_equal_code_objects(self):
+ yield self.st, "f=lambda:1;g=lambda:1.0;x=g()", 'type(x)', float
+ yield (self.st, "x=(lambda: (-0.0, 0.0), lambda: (0.0, -0.0))[1]()",
+ 'repr(x)', '(0.0, -0.0)')
+
class AppTestCompiler:
diff --git a/pypy/module/_cffi_backend/__init__.py b/pypy/module/_cffi_backend/__init__.py
--- a/pypy/module/_cffi_backend/__init__.py
+++ b/pypy/module/_cffi_backend/__init__.py
@@ -2,7 +2,7 @@
from pypy.interpreter.mixedmodule import MixedModule
from rpython.rlib import rdynload, clibffi
-VERSION = "1.3.1"
+VERSION = "1.4.2"
FFI_DEFAULT_ABI = clibffi.FFI_DEFAULT_ABI
try:
diff --git a/pypy/module/_cffi_backend/call_python.py b/pypy/module/_cffi_backend/call_python.py
--- a/pypy/module/_cffi_backend/call_python.py
+++ b/pypy/module/_cffi_backend/call_python.py
@@ -40,10 +40,9 @@
at least 8 bytes in size.
"""
from pypy.module._cffi_backend.ccallback import reveal_callback
+ from rpython.rlib import rgil
- after = rffi.aroundstate.after
- if after:
- after()
+ rgil.acquire()
rffi.stackcounter.stacks_counter += 1
llop.gc_stack_bottom(lltype.Void) # marker for trackgcroot.py
@@ -71,9 +70,7 @@
cerrno._errno_before(rffi.RFFI_ERR_ALL | rffi.RFFI_ALT_ERRNO)
rffi.stackcounter.stacks_counter -= 1
- before = rffi.aroundstate.before
- if before:
- before()
+ rgil.release()
def get_ll_cffi_call_python():
diff --git a/pypy/module/_cffi_backend/lib_obj.py b/pypy/module/_cffi_backend/lib_obj.py
--- a/pypy/module/_cffi_backend/lib_obj.py
+++ b/pypy/module/_cffi_backend/lib_obj.py
@@ -194,6 +194,8 @@
return self.dir1(ignore_global_vars=True)
if is_getattr and attr == '__dict__':
return self.full_dict_copy()
+ if is_getattr and attr == '__class__':
+ return self.space.type(self)
if is_getattr and attr == '__name__':
return self.descr_repr()
raise oefmt(self.space.w_AttributeError,
diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py
--- a/pypy/module/_cffi_backend/test/_backend_test_c.py
+++ b/pypy/module/_cffi_backend/test/_backend_test_c.py
@@ -1,7 +1,7 @@
# ____________________________________________________________
import sys
-assert __version__ == "1.3.1", ("This test_c.py file is for testing a version"
+assert __version__ == "1.4.2", ("This test_c.py file is for testing a version"
" of cffi that differs from the one that we"
" get from 'import _cffi_backend'")
if sys.version_info < (3,):
diff --git a/pypy/module/_cffi_backend/test/test_ffi_obj.py b/pypy/module/_cffi_backend/test/test_ffi_obj.py
--- a/pypy/module/_cffi_backend/test/test_ffi_obj.py
+++ b/pypy/module/_cffi_backend/test/test_ffi_obj.py
@@ -12,6 +12,7 @@
p = ffi.new("int *")
p[0] = -42
assert p[0] == -42
+ assert type(ffi) is ffi.__class__ is _cffi1_backend.FFI
def test_ffi_subclass(self):
import _cffi_backend as _cffi1_backend
@@ -22,6 +23,7 @@
assert foo.x == 42
p = foo.new("int *")
assert p[0] == 0
+ assert type(foo) is foo.__class__ is FOO
def test_ffi_no_argument(self):
import _cffi_backend as _cffi1_backend
diff --git a/pypy/module/_cffi_backend/test/test_recompiler.py b/pypy/module/_cffi_backend/test/test_recompiler.py
--- a/pypy/module/_cffi_backend/test/test_recompiler.py
+++ b/pypy/module/_cffi_backend/test/test_recompiler.py
@@ -16,8 +16,8 @@
from cffi import ffiplatform
except ImportError:
py.test.skip("system cffi module not found or older than 1.0.0")
- if cffi.__version_info__ < (1, 3, 0):
- py.test.skip("system cffi module needs to be at least 1.3.0")
+ if cffi.__version_info__ < (1, 4, 0):
+ py.test.skip("system cffi module needs to be at least 1.4.0")
space.appexec([], """():
import _cffi_backend # force it to be initialized
""")
@@ -1029,6 +1029,7 @@
assert hasattr(lib, '__dict__')
assert lib.__all__ == ['MYFOO', 'mybar'] # but not 'myvar'
assert lib.__name__ == repr(lib)
+ assert lib.__class__ is type(lib)
def test_macro_var_callback(self):
ffi, lib = self.prepare(
diff --git a/pypy/module/_file/test/test_large_file.py b/pypy/module/_file/test/test_large_file.py
--- a/pypy/module/_file/test/test_large_file.py
+++ b/pypy/module/_file/test/test_large_file.py
@@ -1,4 +1,4 @@
-import py
+import py, sys
from pypy.module._file.test.test_file import getfile
@@ -13,6 +13,12 @@
def setup_method(self, meth):
if getattr(meth, 'need_sparse_files', False):
from rpython.translator.c.test.test_extfunc import need_sparse_files
+ if sys.maxsize < 2**32 and not self.runappdirect:
+ # this fails because it uses ll2ctypes to call the posix
+ # functions like 'open' and 'lseek', whereas a real compiled
+ # C program would macro-define them to their longlong versions
+ py.test.skip("emulation of files can't use "
+ "larger-than-long offsets")
need_sparse_files()
def test_large_seek_offsets(self):
diff --git a/pypy/module/_io/interp_io.py b/pypy/module/_io/interp_io.py
--- a/pypy/module/_io/interp_io.py
+++ b/pypy/module/_io/interp_io.py
@@ -7,7 +7,9 @@
from pypy.module.exceptions.interp_exceptions import W_IOError
from pypy.module._io.interp_fileio import W_FileIO
from pypy.module._io.interp_textio import W_TextIOWrapper
-from rpython.rtyper.module.ll_os_stat import STAT_FIELD_TYPES
+from rpython.rlib.rposix_stat import STAT_FIELD_TYPES
+
+HAS_BLKSIZE = 'st_blksize' in STAT_FIELD_TYPES
class Cache:
@@ -118,7 +120,7 @@
if buffering < 0:
buffering = DEFAULT_BUFFER_SIZE
- if 'st_blksize' in STAT_FIELD_TYPES:
+ if HAS_BLKSIZE:
fileno = space.c_int_w(space.call_method(w_raw, "fileno"))
try:
st = os.fstat(fileno)
diff --git a/pypy/module/_socket/test/test_sock_app.py b/pypy/module/_socket/test/test_sock_app.py
--- a/pypy/module/_socket/test/test_sock_app.py
+++ b/pypy/module/_socket/test/test_sock_app.py
@@ -251,7 +251,7 @@
from pypy.module._socket.interp_socket import addr_as_object
if not hasattr(rsocket._c, 'sockaddr_ll'):
py.test.skip("posix specific test")
- # HACK: To get the correct interface numer of lo, which in most cases is 1,
+ # HACK: To get the correct interface number of lo, which in most cases is 1,
# but can be anything (i.e. 39), we need to call the libc function
# if_nametoindex to get the correct index
import ctypes
@@ -513,7 +513,7 @@
def test_getsetsockopt(self):
import _socket as socket
import struct
- # A socket sould start with reuse == 0
+ # A socket should start with reuse == 0
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
reuse = s.getsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR)
assert reuse == 0
@@ -627,6 +627,26 @@
self.foo = _socket.socket()
+class AppTestNetlink:
+ def setup_class(cls):
+ if not hasattr(os, 'getpid'):
+ py.test.skip("AF_NETLINK needs os.getpid()")
+ w_ok = space.appexec([], "(): import _socket; " +
+ "return hasattr(_socket, 'AF_NETLINK')")
+ if not space.is_true(w_ok):
+ py.test.skip("no AF_NETLINK on this platform")
+ cls.space = space
+
+ def test_connect_to_kernel_netlink_routing_socket(self):
+ import _socket, os
+ s = _socket.socket(_socket.AF_NETLINK, _socket.SOCK_DGRAM, _socket.NETLINK_ROUTE)
+ assert s.getsockname() == (0L, 0L)
+ s.bind((0, 0))
+ a, b = s.getsockname()
+ assert a == os.getpid()
+ assert b == 0
+
+
class AppTestPacket:
def setup_class(cls):
if not hasattr(os, 'getuid') or os.getuid() != 0:
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
@@ -124,7 +124,7 @@
METH_COEXIST METH_STATIC METH_CLASS
METH_NOARGS METH_VARARGS METH_KEYWORDS METH_O
Py_TPFLAGS_HEAPTYPE Py_TPFLAGS_HAVE_CLASS
-Py_LT Py_LE Py_EQ Py_NE Py_GT Py_GE
+Py_LT Py_LE Py_EQ Py_NE Py_GT Py_GE Py_TPFLAGS_CHECKTYPES
""".split()
for name in constant_names:
setattr(CConfig_constants, name, rffi_platform.ConstantInteger(name))
@@ -601,6 +601,7 @@
# Make the wrapper for the cases (1) and (2)
def make_wrapper(space, callable, gil=None):
"NOT_RPYTHON"
+ from rpython.rlib import rgil
names = callable.api_func.argnames
argtypes_enum_ui = unrolling_iterable(enumerate(zip(callable.api_func.argtypes,
[name.startswith("w_") for name in names])))
@@ -616,9 +617,7 @@
# we hope that malloc removal removes the newtuple() that is
# inserted exactly here by the varargs specializer
if gil_acquire:
- after = rffi.aroundstate.after
- if after:
- after()
+ rgil.acquire()
rffi.stackcounter.stacks_counter += 1
llop.gc_stack_bottom(lltype.Void) # marker for trackgcroot.py
retval = fatal_value
@@ -691,9 +690,7 @@
pypy_debug_catch_fatal_exception()
rffi.stackcounter.stacks_counter -= 1
if gil_release:
- before = rffi.aroundstate.before
- if before:
- before()
+ rgil.release()
return retval
callable._always_inline_ = 'try'
wrapper.__name__ = "wrapper for %r" % (callable, )
diff --git a/pypy/module/cpyext/slotdefs.py b/pypy/module/cpyext/slotdefs.py
--- a/pypy/module/cpyext/slotdefs.py
+++ b/pypy/module/cpyext/slotdefs.py
@@ -4,14 +4,14 @@
from rpython.rtyper.lltypesystem import rffi, lltype
from pypy.module.cpyext.api import (
- cpython_api, generic_cpy_call, PyObject, Py_ssize_t)
+ cpython_api, generic_cpy_call, PyObject, Py_ssize_t, Py_TPFLAGS_CHECKTYPES)
from pypy.module.cpyext.typeobjectdefs import (
unaryfunc, wrapperfunc, ternaryfunc, PyTypeObjectPtr, binaryfunc,
getattrfunc, getattrofunc, setattrofunc, lenfunc, ssizeargfunc, inquiry,
ssizessizeargfunc, ssizeobjargproc, iternextfunc, initproc, richcmpfunc,
cmpfunc, hashfunc, descrgetfunc, descrsetfunc, objobjproc, objobjargproc,
readbufferproc)
-from pypy.module.cpyext.pyobject import from_ref
+from pypy.module.cpyext.pyobject import from_ref, make_ref, Py_DecRef
from pypy.module.cpyext.pyerrors import PyErr_Occurred
from pypy.module.cpyext.state import State
from pypy.interpreter.error import OperationError, oefmt
@@ -65,22 +65,24 @@
func_binary = rffi.cast(binaryfunc, func)
check_num_args(space, w_args, 1)
args_w = space.fixedview(w_args)
-
- if not space.is_true(space.issubtype(space.type(args_w[0]),
- space.type(w_self))):
+ ref = make_ref(space, w_self)
+ if (not ref.c_ob_type.c_tp_flags & Py_TPFLAGS_CHECKTYPES and
+ not space.is_true(space.issubtype(space.type(args_w[0]),
+ space.type(w_self)))):
return space.w_NotImplemented
-
+ Py_DecRef(space, ref)
return generic_cpy_call(space, func_binary, w_self, args_w[0])
def wrap_binaryfunc_r(space, w_self, w_args, func):
func_binary = rffi.cast(binaryfunc, func)
check_num_args(space, w_args, 1)
args_w = space.fixedview(w_args)
-
- if not space.is_true(space.issubtype(space.type(args_w[0]),
- space.type(w_self))):
+ ref = make_ref(space, w_self)
+ if (not ref.c_ob_type.c_tp_flags & Py_TPFLAGS_CHECKTYPES and
+ not space.is_true(space.issubtype(space.type(args_w[0]),
+ space.type(w_self)))):
return space.w_NotImplemented
-
+ Py_DecRef(space, ref)
return generic_cpy_call(space, func_binary, args_w[0], w_self)
def wrap_inquirypred(space, w_self, w_args, func):
@@ -378,6 +380,17 @@
space.call_function(delattr_fn, w_self, w_name)
return 0
api_func = slot_tp_setattro.api_func
+ elif name == 'tp_getattro':
+ getattr_fn = w_type.getdictvalue(space, '__getattribute__')
+ if getattr_fn is None:
+ return
+
+ @cpython_api([PyObject, PyObject], PyObject,
+ error=lltype.nullptr(rffi.VOIDP.TO), external=True)
+ @func_renamer("cpyext_tp_getattro_%s" % (typedef.name,))
+ def slot_tp_getattro(space, w_self, w_name):
+ return space.call_function(getattr_fn, w_self, w_name)
+ api_func = slot_tp_getattro.api_func
else:
return
diff --git a/pypy/module/cpyext/test/test_typeobject.py b/pypy/module/cpyext/test/test_typeobject.py
--- a/pypy/module/cpyext/test/test_typeobject.py
+++ b/pypy/module/cpyext/test/test_typeobject.py
@@ -387,12 +387,53 @@
PyErr_SetString(PyExc_ValueError, "recursive tp_setattro");
return NULL;
}
+ if (!args->ob_type->tp_getattro)
+ {
+ PyErr_SetString(PyExc_ValueError, "missing tp_getattro");
+ return NULL;
+ }
+ if (args->ob_type->tp_getattro ==
+ args->ob_type->tp_base->tp_getattro)
+ {
+ PyErr_SetString(PyExc_ValueError, "recursive tp_getattro");
+ return NULL;
+ }
Py_RETURN_TRUE;
'''
)
])
assert module.test_type(type(None))
+ def test_tp_getattro(self):
+ module = self.import_extension('foo', [
+ ("test_tp_getattro", "METH_VARARGS",
+ '''
+ PyObject *obj = PyTuple_GET_ITEM(args, 0);
+ PyIntObject *value = PyTuple_GET_ITEM(args, 1);
+ if (!obj->ob_type->tp_getattro)
+ {
+ PyErr_SetString(PyExc_ValueError, "missing tp_getattro");
+ return NULL;
+ }
+ PyObject *name = PyString_FromString("attr1");
+ PyIntObject *attr1 = obj->ob_type->tp_getattro(obj, name);
+ if (attr1->ob_ival != value->ob_ival)
+ {
+ PyErr_SetString(PyExc_ValueError,
+ "tp_getattro returned wrong value");
+ return NULL;
+ }
+ Py_DECREF(name);
+ Py_DECREF(attr1);
+ Py_RETURN_TRUE;
+ '''
+ )
+ ])
+ class C:
+ def __init__(self):
+ self.attr1 = 123
+ assert module.test_tp_getattro(C(), 123)
+
def test_nb_int(self):
module = self.import_extension('foo', [
("nb_int", "METH_O",
@@ -601,45 +642,92 @@
if self.runappdirect:
py.test.xfail('segfault')
module = self.import_extension('foo', [
- ("new_obj", "METH_NOARGS",
+ ("newInt", "METH_VARARGS",
"""
- FooObject *fooObj;
+ IntLikeObject *intObj;
+ long intval;
- Foo_Type.tp_as_number = &foo_as_number;
- foo_as_number.nb_add = foo_nb_add_call;
- if (PyType_Ready(&Foo_Type) < 0) return NULL;
- fooObj = PyObject_New(FooObject, &Foo_Type);
- if (!fooObj) {
+ if (!PyArg_ParseTuple(args, "i", &intval))
+ return NULL;
+
+ IntLike_Type.tp_as_number = &intlike_as_number;
+ IntLike_Type.tp_flags |= Py_TPFLAGS_CHECKTYPES;
+ intlike_as_number.nb_add = intlike_nb_add;
+ if (PyType_Ready(&IntLike_Type) < 0) return NULL;
+ intObj = PyObject_New(IntLikeObject, &IntLike_Type);
+ if (!intObj) {
return NULL;
}
- return (PyObject *)fooObj;
+ intObj->ival = intval;
+ return (PyObject *)intObj;
+ """),
+ ("newIntNoOp", "METH_VARARGS",
+ """
+ IntLikeObjectNoOp *intObjNoOp;
+ long intval;
+
+ if (!PyArg_ParseTuple(args, "i", &intval))
+ return NULL;
+
+ IntLike_Type_NoOp.tp_flags |= Py_TPFLAGS_CHECKTYPES;
+ if (PyType_Ready(&IntLike_Type_NoOp) < 0) return NULL;
+ intObjNoOp = PyObject_New(IntLikeObjectNoOp, &IntLike_Type_NoOp);
+ if (!intObjNoOp) {
+ return NULL;
+ }
+
+ intObjNoOp->ival = intval;
+ return (PyObject *)intObjNoOp;
""")],
"""
typedef struct
{
PyObject_HEAD
- } FooObject;
+ long ival;
+ } IntLikeObject;
static PyObject *
- foo_nb_add_call(PyObject *self, PyObject *other)
+ intlike_nb_add(PyObject *self, PyObject *other)
{
- return PyInt_FromLong(42);
+ long val1 = ((IntLikeObject *)(self))->ival;
+ if (PyInt_Check(other)) {
+ long val2 = PyInt_AsLong(other);
+ return PyInt_FromLong(val1+val2);
+ }
+
+ long val2 = ((IntLikeObject *)(other))->ival;
+ return PyInt_FromLong(val1+val2);
}
- PyTypeObject Foo_Type = {
+ PyTypeObject IntLike_Type = {
PyObject_HEAD_INIT(0)
/*ob_size*/ 0,
- /*tp_name*/ "Foo",
- /*tp_basicsize*/ sizeof(FooObject),
+ /*tp_name*/ "IntLike",
+ /*tp_basicsize*/ sizeof(IntLikeObject),
};
- static PyNumberMethods foo_as_number;
+ static PyNumberMethods intlike_as_number;
+
+ typedef struct
+ {
+ PyObject_HEAD
+ long ival;
+ } IntLikeObjectNoOp;
+
+ PyTypeObject IntLike_Type_NoOp = {
+ PyObject_HEAD_INIT(0)
+ /*ob_size*/ 0,
+ /*tp_name*/ "IntLikeNoOp",
+ /*tp_basicsize*/ sizeof(IntLikeObjectNoOp),
+ };
""")
- a = module.new_obj()
- b = module.new_obj()
+ a = module.newInt(1)
+ b = module.newInt(2)
c = 3
- assert (a + b) == 42
- raises(TypeError, "b + c")
+ d = module.newIntNoOp(4)
+ assert (a + b) == 3
+ assert (b + c) == 5
+ assert (d + a) == 5
def test_tp_new_in_subclass_of_type(self):
skip("BROKEN")
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
@@ -582,6 +582,8 @@
pto.c_tp_free = base.c_tp_free
if not pto.c_tp_setattro:
pto.c_tp_setattro = base.c_tp_setattro
+ if not pto.c_tp_getattro:
+ pto.c_tp_getattro = base.c_tp_getattro
finally:
Py_DecRef(space, base_pyo)
@@ -652,6 +654,12 @@
PyObject_GenericSetAttr.api_func.functype,
PyObject_GenericSetAttr.api_func.get_wrapper(space))
+ if not pto.c_tp_getattro:
+ from pypy.module.cpyext.object import PyObject_GenericGetAttr
+ pto.c_tp_getattro = llhelper(
+ PyObject_GenericGetAttr.api_func.functype,
+ PyObject_GenericGetAttr.api_func.get_wrapper(space))
+
if w_obj.is_cpytype():
Py_DecRef(space, pto.c_tp_dict)
w_dict = w_obj.getdict(space)
diff --git a/pypy/module/mmap/test/test_mmap.py b/pypy/module/mmap/test/test_mmap.py
--- a/pypy/module/mmap/test/test_mmap.py
+++ b/pypy/module/mmap/test/test_mmap.py
@@ -1,6 +1,6 @@
from __future__ import with_statement
from rpython.tool.udir import udir
-import os
+import os, sys, py
class AppTestMMap:
spaceconfig = dict(usemodules=('mmap',))
@@ -8,6 +8,15 @@
def setup_class(cls):
cls.w_tmpname = cls.space.wrap(str(udir.join('mmap-')))
+ def setup_method(self, meth):
+ if getattr(meth, 'is_large', False):
+ if sys.maxsize < 2**32 and not self.runappdirect:
+ # this fails because it uses ll2ctypes to call the posix
+ # functions like 'open' and 'lseek', whereas a real compiled
+ # C program would macro-define them to their longlong versions
+ py.test.skip("emulation of files can't use "
+ "larger-than-long offsets")
+
def test_page_size(self):
import mmap
assert mmap.PAGESIZE > 0
@@ -648,6 +657,7 @@
assert m[0xFFFFFFF] == b'A'
finally:
m.close()
+ test_large_offset.is_large = True
def test_large_filesize(self):
import mmap
@@ -665,6 +675,7 @@
assert m.size() == 0x180000000
finally:
m.close()
+ test_large_filesize.is_large = True
def test_all(self):
# this is a global test, ported from test_mmap.py
diff --git a/pypy/module/posix/__init__.py b/pypy/module/posix/__init__.py
--- a/pypy/module/posix/__init__.py
+++ b/pypy/module/posix/__init__.py
@@ -1,5 +1,5 @@
from pypy.interpreter.mixedmodule import MixedModule
-from rpython.rtyper.module.ll_os import RegisterOs
+from rpython.rlib import rposix
import os
exec 'import %s as posix' % os.name
@@ -172,7 +172,7 @@
if hasattr(os, 'chroot'):
interpleveldefs['chroot'] = 'interp_posix.chroot'
- for name in RegisterOs.w_star:
+ for name in rposix.WAIT_MACROS:
if hasattr(os, name):
interpleveldefs[name] = 'interp_posix.' + name
diff --git a/pypy/module/posix/interp_posix.py b/pypy/module/posix/interp_posix.py
--- a/pypy/module/posix/interp_posix.py
+++ b/pypy/module/posix/interp_posix.py
@@ -1,12 +1,11 @@
import os
import sys
-from rpython.rlib import rposix, objectmodel, rurandom
+from rpython.rlib import rposix, rposix_stat
+from rpython.rlib import objectmodel, rurandom
from rpython.rlib.objectmodel import specialize
from rpython.rlib.rarithmetic import r_longlong, intmask
from rpython.rlib.unroll import unrolling_iterable
-from rpython.rtyper.module import ll_os_stat
-from rpython.rtyper.module.ll_os import RegisterOs
from pypy.interpreter.gateway import unwrap_spec
from pypy.interpreter.error import OperationError, wrap_oserror, wrap_oserror2
@@ -43,6 +42,8 @@
return space.str0_w(w_obj)
class FileEncoder(object):
+ is_unicode = True
+
def __init__(self, space, w_obj):
self.space = space
self.w_obj = w_obj
@@ -54,6 +55,8 @@
return self.space.unicode0_w(self.w_obj)
class FileDecoder(object):
+ is_unicode = False
+
def __init__(self, space, w_obj):
self.space = space
self.w_obj = w_obj
@@ -212,13 +215,13 @@
# ____________________________________________________________
-STAT_FIELDS = unrolling_iterable(enumerate(ll_os_stat.STAT_FIELDS))
+STAT_FIELDS = unrolling_iterable(enumerate(rposix_stat.STAT_FIELDS))
-STATVFS_FIELDS = unrolling_iterable(enumerate(ll_os_stat.STATVFS_FIELDS))
+STATVFS_FIELDS = unrolling_iterable(enumerate(rposix_stat.STATVFS_FIELDS))
def build_stat_result(space, st):
FIELDS = STAT_FIELDS # also when not translating at all
- lst = [None] * ll_os_stat.N_INDEXABLE_FIELDS
+ lst = [None] * rposix_stat.N_INDEXABLE_FIELDS
w_keywords = space.newdict()
stat_float_times = space.fromcache(StatState).stat_float_times
for i, (name, TYPE) in FIELDS:
@@ -226,7 +229,7 @@
if name in ('st_atime', 'st_mtime', 'st_ctime'):
value = int(value) # rounded to an integer for indexed access
w_value = space.wrap(value)
- if i < ll_os_stat.N_INDEXABLE_FIELDS:
+ if i < rposix_stat.N_INDEXABLE_FIELDS:
lst[i] = w_value
else:
space.setitem(w_keywords, space.wrap(name), w_value)
@@ -254,7 +257,7 @@
def build_statvfs_result(space, st):
- vals_w = [None] * len(ll_os_stat.STATVFS_FIELDS)
+ vals_w = [None] * len(rposix_stat.STATVFS_FIELDS)
for i, (name, _) in STATVFS_FIELDS:
vals_w[i] = space.wrap(getattr(st, name))
w_tuple = space.newtuple(vals_w)
@@ -267,7 +270,7 @@
"""Perform a stat system call on the file referenced to by an open
file descriptor."""
try:
- st = os.fstat(fd)
+ st = rposix_stat.fstat(fd)
except OSError, e:
raise wrap_oserror(space, e)
else:
@@ -289,7 +292,7 @@
"""
try:
- st = dispatch_filename(rposix.stat)(space, w_path)
+ st = dispatch_filename(rposix_stat.stat)(space, w_path)
except OSError, e:
raise wrap_oserror2(space, e, w_path)
else:
@@ -298,7 +301,7 @@
def lstat(space, w_path):
"Like stat(path), but do no follow symbolic links."
try:
- st = dispatch_filename(rposix.lstat)(space, w_path)
+ st = dispatch_filename(rposix_stat.lstat)(space, w_path)
except OSError, e:
raise wrap_oserror2(space, e, w_path)
else:
@@ -327,7 +330,7 @@
@unwrap_spec(fd=c_int)
def fstatvfs(space, fd):
try:
- st = os.fstatvfs(fd)
+ st = rposix_stat.fstatvfs(fd)
except OSError as e:
raise wrap_oserror(space, e)
else:
@@ -336,7 +339,7 @@
def statvfs(space, w_path):
try:
- st = dispatch_filename(rposix.statvfs)(space, w_path)
+ st = dispatch_filename(rposix_stat.statvfs)(space, w_path)
except OSError as e:
raise wrap_oserror2(space, e, w_path)
else:
@@ -427,11 +430,11 @@
try:
if space.isinstance_w(w_path, space.w_unicode):
path = FileEncoder(space, w_path)
- fullpath = rposix._getfullpathname(path)
+ fullpath = rposix.getfullpathname(path)
w_fullpath = space.wrap(fullpath)
else:
path = space.str0_w(w_path)
- fullpath = rposix._getfullpathname(path)
+ fullpath = rposix.getfullpathname(path)
w_fullpath = space.wrap(fullpath)
except OSError, e:
raise wrap_oserror2(space, e, w_path)
@@ -661,7 +664,7 @@
def kill(space, pid, sig):
"Kill a process with a signal."
try:
- rposix.os_kill(pid, sig)
+ rposix.kill(pid, sig)
except OSError, e:
raise wrap_oserror(space, e)
@@ -677,7 +680,7 @@
"""Abort the interpreter immediately. This 'dumps core' or otherwise fails
in the hardest way possible on the hosting operating system."""
import signal
- rposix.os_kill(os.getpid(), signal.SIGABRT)
+ rposix.kill(os.getpid(), signal.SIGABRT)
@unwrap_spec(src='str0', dst='str0')
def link(space, src, dst):
@@ -1199,7 +1202,7 @@
raise wrap_oserror(space, e)
def declare_new_w_star(name):
- if name in RegisterOs.w_star_returning_int:
+ if name in ('WEXITSTATUS', 'WSTOPSIG', 'WTERMSIG'):
@unwrap_spec(status=c_int)
def WSTAR(space, status):
return space.wrap(getattr(os, name)(status))
@@ -1211,7 +1214,7 @@
WSTAR.func_name = name
return WSTAR
-for name in RegisterOs.w_star:
+for name in rposix.WAIT_MACROS:
if hasattr(os, name):
func = declare_new_w_star(name)
globals()[name] = func
diff --git a/pypy/module/posix/test/test_posix2.py b/pypy/module/posix/test/test_posix2.py
--- a/pypy/module/posix/test/test_posix2.py
+++ b/pypy/module/posix/test/test_posix2.py
@@ -6,8 +6,8 @@
from rpython.tool.udir import udir
from pypy.tool.pytest.objspace import gettestobjspace
from pypy.conftest import pypydir
-from rpython.rtyper.module.ll_os import RegisterOs
from rpython.translator.c.test.test_extfunc import need_sparse_files
+from rpython.rlib import rposix
import os
import py
import sys
@@ -93,6 +93,12 @@
def setup_method(self, meth):
if getattr(meth, 'need_sparse_files', False):
+ if sys.maxsize < 2**32 and not self.runappdirect:
+ # this fails because it uses ll2ctypes to call the posix
+ # functions like 'open' and 'lseek', whereas a real compiled
+ # C program would macro-define them to their longlong versions
+ py.test.skip("emulation of files can't use "
+ "larger-than-long offsets")
need_sparse_files()
def test_posix_is_pypy_s(self):
@@ -576,7 +582,7 @@
raises(TypeError, "os.utime('xxx', 3)")
raises(OSError, "os.utime('somefilewhichihopewouldneverappearhere', None)")
- for name in RegisterOs.w_star:
+ for name in rposix.WAIT_MACROS:
if hasattr(os, name):
values = [0, 1, 127, 128, 255]
code = py.code.Source("""
diff --git a/pypy/module/signal/__init__.py b/pypy/module/signal/__init__.py
--- a/pypy/module/signal/__init__.py
+++ b/pypy/module/signal/__init__.py
@@ -48,3 +48,6 @@
use_bytecode_counter=False)
space.actionflag.__class__ = interp_signal.SignalActionFlag
# xxx yes I know the previous line is a hack
+
+ def startup(self, space):
+ space.check_signal_action.startup(space)
diff --git a/pypy/module/signal/interp_signal.py b/pypy/module/signal/interp_signal.py
--- a/pypy/module/signal/interp_signal.py
+++ b/pypy/module/signal/interp_signal.py
@@ -63,19 +63,25 @@
AsyncAction.__init__(self, space)
self.pending_signal = -1
self.fire_in_another_thread = False
- if self.space.config.objspace.usemodules.thread:
- from pypy.module.thread import gil
- gil.after_thread_switch = self._after_thread_switch
+ #
+ @rgc.no_collect
+ def _after_thread_switch():
+ if self.fire_in_another_thread:
+ if self.space.threadlocals.signals_enabled():
+ self.fire_in_another_thread = False
+ self.space.actionflag.rearm_ticker()
+ # this occurs when we just switched to the main thread
+ # and there is a signal pending: we force the ticker to
+ # -1, which should ensure perform() is called quickly.
+ self._after_thread_switch = _after_thread_switch
+ # ^^^ so that 'self._after_thread_switch' can be annotated as a
+ # constant
- @rgc.no_collect
- def _after_thread_switch(self):
- if self.fire_in_another_thread:
- if self.space.threadlocals.signals_enabled():
- self.fire_in_another_thread = False
- self.space.actionflag.rearm_ticker()
- # this occurs when we just switched to the main thread
- # and there is a signal pending: we force the ticker to
- # -1, which should ensure perform() is called quickly.
+ def startup(self, space):
+ # this is translated
+ if space.config.objspace.usemodules.thread:
+ from rpython.rlib import rgil
+ rgil.invoke_after_thread_switch(self._after_thread_switch)
def perform(self, executioncontext, frame):
self._poll_for_signals()
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/backend_tests.py b/pypy/module/test_lib_pypy/cffi_tests/cffi0/backend_tests.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi0/backend_tests.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi0/backend_tests.py
@@ -1353,8 +1353,8 @@
ffi = FFI(backend=self.Backend())
ffi.cdef("enum foo;")
from cffi import __version_info__
- if __version_info__ < (1, 4):
- py.test.skip("re-enable me in version 1.4")
+ if __version_info__ < (1, 5):
+ py.test.skip("re-enable me in version 1.5")
e = py.test.raises(CDefError, ffi.cast, "enum foo", -1)
assert str(e.value) == (
"'enum foo' has no values explicitly defined: refusing to guess "
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_function.py b/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_function.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_function.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi0/test_function.py
@@ -465,10 +465,22 @@
ffi = FFI(backend=self.Backend())
ffi.cdef("double __stdcall sin(double x);") # stdcall ignored
m = ffi.dlopen(lib_m)
- if (sys.platform == 'win32' and sys.maxsize < 2**32 and
+ if (sys.platform == 'win32' and sys.maxsize < 2**32 and
self.Backend is not CTypesBackend):
assert "double(__stdcall *)(double)" in str(ffi.typeof(m.sin))
else:
assert "double(*)(double)" in str(ffi.typeof(m.sin))
x = m.sin(1.23)
assert x == math.sin(1.23)
+
+ def test_dir_on_dlopen_lib(self):
+ ffi = FFI(backend=self.Backend())
+ ffi.cdef("""
+ typedef enum { MYE1, MYE2 } myenum_t;
+ double myfunc(double);
+ double myvar;
+ const double myconst;
+ #define MYFOO 42
+ """)
+ m = ffi.dlopen(lib_m)
+ assert dir(m) == ['MYE1', 'MYE2', 'MYFOO', 'myconst', 'myfunc', 'myvar']
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_ffi_obj.py b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_ffi_obj.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_ffi_obj.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_ffi_obj.py
@@ -8,6 +8,7 @@
p = ffi.new("int *")
p[0] = -42
assert p[0] == -42
+ assert type(ffi) is ffi.__class__ is _cffi1_backend.FFI
def test_ffi_subclass():
class FOO(_cffi1_backend.FFI):
@@ -17,6 +18,7 @@
assert foo.x == 42
p = foo.new("int *")
assert p[0] == 0
+ assert type(foo) is foo.__class__ is FOO
def test_ffi_no_argument():
py.test.raises(TypeError, _cffi1_backend.FFI, 42)
@@ -472,7 +474,11 @@
assert seen == [1] * (i + 1)
def test_init_once_multithread_failure():
- import thread, time
+ if sys.version_info < (3,):
+ import thread
+ else:
+ import _thread as thread
+ import time
def do_init():
seen.append('init!')
time.sleep(1)
diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py
--- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py
+++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py
@@ -1157,6 +1157,7 @@
assert hasattr(lib, '__dict__')
assert lib.__all__ == ['MYFOO', 'mybar'] # but not 'myvar'
assert lib.__name__ == repr(lib)
+ assert lib.__class__ is type(lib)
def test_macro_var_callback():
ffi = FFI()
diff --git a/pypy/module/thread/gil.py b/pypy/module/thread/gil.py
--- a/pypy/module/thread/gil.py
+++ b/pypy/module/thread/gil.py
@@ -11,7 +11,6 @@
from pypy.module.thread.error import wrap_thread_error
from pypy.interpreter.executioncontext import PeriodicAsyncAction
from pypy.module.thread.threadlocals import OSThreadLocals
-from rpython.rlib.objectmodel import invoke_around_extcall
class GILThreadLocals(OSThreadLocals):
"""A version of OSThreadLocals that enforces a GIL."""
@@ -23,34 +22,21 @@
space.actionflag.register_periodic_action(GILReleaseAction(space),
use_bytecode_counter=True)
- def _initialize_gil(self, space):
- rgil.gil_allocate()
-
def setup_threads(self, space):
"""Enable threads in the object space, if they haven't already been."""
if not self.gil_ready:
- self._initialize_gil(space)
+ # Note: this is a quasi-immutable read by module/pypyjit/interp_jit
+ # It must be changed (to True) only if it was really False before
+ rgil.allocate()
self.gil_ready = True
result = True
else:
result = False # already set up
-
- # add the GIL-releasing callback around external function calls.
- #
- # XXX we assume a single space, but this is not quite true during
- # testing; for example, if you run the whole of test_lock you get
- # a deadlock caused by the first test's space being reused by
- # test_lock_again after the global state was cleared by
- # test_compile_lock. As a workaround, we repatch these global
- # fields systematically.
- invoke_around_extcall(before_external_call, after_external_call)
return result
- def reinit_threads(self, space):
- "Called in the child process after a fork()"
- OSThreadLocals.reinit_threads(self, space)
- if self.gil_ready: # re-initialize the gil if needed
- self._initialize_gil(space)
+ ## def reinit_threads(self, space):
+ ## "Called in the child process after a fork()"
+ ## OSThreadLocals.reinit_threads(self, space)
class GILReleaseAction(PeriodicAsyncAction):
@@ -59,43 +45,4 @@
"""
def perform(self, executioncontext, frame):
- do_yield_thread()
-
-
-after_thread_switch = lambda: None # hook for signal.py
-
-def before_external_call():
- # this function must not raise, in such a way that the exception
- # transformer knows that it cannot raise!
- rgil.gil_release()
-before_external_call._gctransformer_hint_cannot_collect_ = True
-before_external_call._dont_reach_me_in_del_ = True
-
-def after_external_call():
- rgil.gil_acquire()
- rthread.gc_thread_run()
- after_thread_switch()
-after_external_call._gctransformer_hint_cannot_collect_ = True
-after_external_call._dont_reach_me_in_del_ = True
-
-# The _gctransformer_hint_cannot_collect_ hack is needed for
-# translations in which the *_external_call() functions are not inlined.
-# They tell the gctransformer not to save and restore the local GC
-# pointers in the shadow stack. This is necessary because the GIL is
-# not held after the call to before_external_call() or before the call
-# to after_external_call().
-
-def do_yield_thread():
- # explicitly release the gil, in a way that tries to give more
- # priority to other threads (as opposed to continuing to run in
- # the same thread).
- if rgil.gil_yield_thread():
- rthread.gc_thread_run()
- after_thread_switch()
-do_yield_thread._gctransformer_hint_close_stack_ = True
-do_yield_thread._dont_reach_me_in_del_ = True
-do_yield_thread._dont_inline_ = True
-
-# do_yield_thread() needs a different hint: _gctransformer_hint_close_stack_.
-# The *_external_call() functions are themselves called only from the rffi
-# module from a helper function that also has this hint.
+ rgil.yield_thread()
diff --git a/pypy/module/thread/test/support.py b/pypy/module/thread/test/support.py
--- a/pypy/module/thread/test/support.py
+++ b/pypy/module/thread/test/support.py
@@ -5,7 +5,7 @@
import errno
from pypy.interpreter.gateway import interp2app, unwrap_spec
-from pypy.module.thread import gil
+from rpython.rlib import rgil
NORMAL_TIMEOUT = 300.0 # 5 minutes
@@ -15,9 +15,9 @@
adaptivedelay = 0.04
limit = time.time() + delay * NORMAL_TIMEOUT
while time.time() <= limit:
- gil.before_external_call()
+ rgil.release()
time.sleep(adaptivedelay)
- gil.after_external_call()
+ rgil.acquire()
gc.collect()
if space.is_true(space.call_function(w_condition)):
return
diff --git a/pypy/module/thread/test/test_gil.py b/pypy/module/thread/test/test_gil.py
--- a/pypy/module/thread/test/test_gil.py
+++ b/pypy/module/thread/test/test_gil.py
@@ -1,5 +1,6 @@
import time
from pypy.module.thread import gil
+from rpython.rlib import rgil
from rpython.rlib.test import test_rthread
from rpython.rlib import rthread as thread
from rpython.rlib.objectmodel import we_are_translated
@@ -55,7 +56,7 @@
assert state.datalen3 == len(state.data)
assert state.datalen4 == len(state.data)
debug_print(main, i, state.datalen4)
- gil.do_yield_thread()
+ rgil.yield_thread()
assert i == j
j += 1
def bootstrap():
@@ -82,9 +83,9 @@
if not still_waiting:
raise ValueError("time out")
still_waiting -= 1
- if not we_are_translated(): gil.before_external_call()
+ if not we_are_translated(): rgil.release()
time.sleep(0.01)
- if not we_are_translated(): gil.after_external_call()
+ if not we_are_translated(): rgil.acquire()
debug_print("leaving!")
i1 = i2 = 0
for tid, i in state.data:
diff --git a/pypy/module/time/interp_time.py b/pypy/module/time/interp_time.py
--- a/pypy/module/time/interp_time.py
+++ b/pypy/module/time/interp_time.py
@@ -482,13 +482,6 @@
secs = pytime.time()
return space.wrap(secs)
-if _WIN:
- class PCCache:
- pass
- pccache = PCCache()
- pccache.divisor = 0.0
- pccache.ctrStart = 0
-
def clock(space):
"""clock() -> floating point number
diff --git a/pypy/objspace/std/listobject.py b/pypy/objspace/std/listobject.py
--- a/pypy/objspace/std/listobject.py
+++ b/pypy/objspace/std/listobject.py
@@ -546,7 +546,6 @@
def descr_getitem(self, space, w_index):
if isinstance(w_index, W_SliceObject):
- # XXX consider to extend rlist's functionality?
length = self.length()
start, stop, step, slicelength = w_index.indices4(space, length)
assert slicelength >= 0
diff --git a/rpython/annotator/bookkeeper.py b/rpython/annotator/bookkeeper.py
--- a/rpython/annotator/bookkeeper.py
+++ b/rpython/annotator/bookkeeper.py
@@ -353,8 +353,9 @@
# * a user-defined bound or unbound method object
# * a frozen pre-built constant (with _freeze_() == True)
# * a bound method of a frozen pre-built constant
+ obj_key = Constant(pyobj)
try:
- return self.descs[pyobj]
+ return self.descs[obj_key]
except KeyError:
if isinstance(pyobj, types.FunctionType):
result = description.FunctionDesc(self, pyobj)
@@ -399,7 +400,7 @@
msg = "unexpected prebuilt constant"
raise Exception("%s: %r" % (msg, pyobj))
result = self.getfrozen(pyobj)
- self.descs[pyobj] = result
+ self.descs[obj_key] = result
return result
def getfrozen(self, pyobj):
diff --git a/rpython/annotator/test/test_annrpython.py b/rpython/annotator/test/test_annrpython.py
--- a/rpython/annotator/test/test_annrpython.py
+++ b/rpython/annotator/test/test_annrpython.py
@@ -3516,6 +3516,32 @@
s = a.build_types(f, [unicode])
assert isinstance(s, annmodel.SomeUnicodeString)
+ def test_extended_slice(self):
+ a = self.RPythonAnnotator()
+ def f(start, end, step):
+ return [1, 2, 3][start:end:step]
+ with py.test.raises(AnnotatorError):
+ a.build_types(f, [int, int, int])
+ a = self.RPythonAnnotator()
+ with py.test.raises(AnnotatorError):
+ a.build_types(f, [annmodel.SomeInteger(nonneg=True),
+ annmodel.SomeInteger(nonneg=True),
+ annmodel.SomeInteger(nonneg=True)])
+ def f(x):
+ return x[::-1]
+ a = self.RPythonAnnotator()
+ with py.test.raises(AnnotatorError):
+ a.build_types(f, [str])
+ def f(x):
+ return x[::2]
+ a = self.RPythonAnnotator()
+ with py.test.raises(AnnotatorError):
+ a.build_types(f, [str])
+ def f(x):
+ return x[1:2:1]
+ a = self.RPythonAnnotator()
+ with py.test.raises(AnnotatorError):
+ a.build_types(f, [str])
def test_negative_slice(self):
def f(s, e):
diff --git a/rpython/annotator/unaryop.py b/rpython/annotator/unaryop.py
--- a/rpython/annotator/unaryop.py
+++ b/rpython/annotator/unaryop.py
@@ -441,7 +441,7 @@
def dict_contains(s_dct, s_element, position):
s_dct.dictdef.generalize_key(s_element)
if s_dct._is_empty(position):
- s_bool =SomeBool()
+ s_bool = SomeBool()
s_bool.const = False
return s_bool
return s_Bool
@@ -686,7 +686,7 @@
enc = s_enc.const
if enc not in ('ascii', 'latin-1', 'utf-8'):
raise AnnotatorError("Encoding %s not supported for unicode" % (enc,))
- return SomeString()
+ return SomeString(no_nul=self.no_nul)
method_encode.can_only_throw = [UnicodeEncodeError]
@@ -719,7 +719,7 @@
enc = s_enc.const
if enc not in ('ascii', 'latin-1', 'utf-8'):
raise AnnotatorError("Encoding %s not supported for strings" % (enc,))
- return SomeUnicodeString()
+ return SomeUnicodeString(no_nul=self.no_nul)
method_decode.can_only_throw = [UnicodeDecodeError]
class __extend__(SomeChar, SomeUnicodeCodePoint):
diff --git a/rpython/flowspace/objspace.py b/rpython/flowspace/objspace.py
--- a/rpython/flowspace/objspace.py
+++ b/rpython/flowspace/objspace.py
@@ -23,7 +23,7 @@
if func.func_code.co_cellvars:
raise ValueError(
"""RPython functions cannot create closures
-Possible casues:
+Possible causes:
Function is inner function
Function uses generator expressions
Lambda expressions
diff --git a/rpython/flowspace/operation.py b/rpython/flowspace/operation.py
--- a/rpython/flowspace/operation.py
+++ b/rpython/flowspace/operation.py
@@ -1,5 +1,5 @@
"""
-This module defines all the SpaceOeprations used in rpython.flowspace.
+This module defines all the SpaceOperations used in rpython.flowspace.
"""
import __builtin__
@@ -196,21 +196,6 @@
return cls._dispatch(type(s_arg))
@classmethod
- def get_specialization(cls, s_arg, *_ignored):
- try:
- impl = getattr(s_arg, cls.opname)
-
- def specialized(annotator, arg, *other_args):
- return impl(*[annotator.annotation(x) for x in other_args])
- try:
- specialized.can_only_throw = impl.can_only_throw
- except AttributeError:
- pass
- return specialized
- except AttributeError:
- return cls._dispatch(type(s_arg))
-
- @classmethod
def register_transform(cls, Some_cls):
def decorator(func):
cls._transform[Some_cls] = func
@@ -523,6 +508,14 @@
*[annotator.annotation(arg) for arg in self.args])
+class NewSlice(HLOperation):
+ opname = 'newslice'
+ canraise = []
+
+ def consider(self, annotator):
+ raise AnnotatorError("Cannot use extended slicing in rpython")
+
+
class Pow(PureOperation):
opname = 'pow'
arity = 3
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
@@ -19,7 +19,6 @@
from rpython.jit.backend.arm.locations import imm, RawSPStackLocation
from rpython.jit.backend.llsupport import symbolic
from rpython.jit.backend.llsupport.gcmap import allocate_gcmap
-from rpython.jit.backend.llsupport.descr import InteriorFieldDescr
from rpython.jit.backend.llsupport.assembler import GuardToken, BaseAssembler
from rpython.jit.backend.llsupport.regalloc import get_scale
from rpython.jit.metainterp.history import (AbstractFailDescr, ConstInt,
@@ -655,31 +654,24 @@
pmc.B_offs(offset, c.EQ)
return fcond
- def emit_op_setfield_gc(self, op, arglocs, regalloc, fcond):
- value_loc, base_loc, ofs, size = arglocs
- scale = get_scale(size.value)
- self._write_to_mem(value_loc, base_loc,
- ofs, imm(scale), fcond)
+ def emit_op_gc_store(self, op, arglocs, regalloc, fcond):
+ value_loc, base_loc, ofs_loc, size_loc = arglocs
+ scale = get_scale(size_loc.value)
+ self._write_to_mem(value_loc, base_loc, ofs_loc, imm(scale), fcond)
return fcond
- emit_op_setfield_raw = emit_op_setfield_gc
- emit_op_zero_ptr_field = emit_op_setfield_gc
-
- def _genop_getfield(self, op, arglocs, regalloc, fcond):
- base_loc, ofs, res, size = arglocs
- signed = op.getdescr().is_field_signed()
- scale = get_scale(size.value)
- self._load_from_mem(res, base_loc, ofs, imm(scale), signed, fcond)
+ def _emit_op_gc_load(self, op, arglocs, regalloc, fcond):
+ base_loc, ofs_loc, res_loc, nsize_loc = arglocs
+ nsize = nsize_loc.value
+ signed = (nsize < 0)
+ scale = get_scale(abs(nsize))
+ self._load_from_mem(res_loc, base_loc, ofs_loc, imm(scale),
+ signed, fcond)
return fcond
- emit_op_getfield_gc_i = _genop_getfield
- emit_op_getfield_gc_r = _genop_getfield
- emit_op_getfield_gc_f = _genop_getfield
- emit_op_getfield_gc_pure_i = _genop_getfield
- emit_op_getfield_gc_pure_r = _genop_getfield
- emit_op_getfield_gc_pure_f = _genop_getfield
- emit_op_getfield_raw_i = _genop_getfield
- emit_op_getfield_raw_f = _genop_getfield
+ emit_op_gc_load_i = _emit_op_gc_load
+ emit_op_gc_load_r = _emit_op_gc_load
+ emit_op_gc_load_f = _emit_op_gc_load
def emit_op_increment_debug_counter(self, op, arglocs, regalloc, fcond):
base_loc, value_loc = arglocs
@@ -688,68 +680,21 @@
self.mc.STR_ri(value_loc.value, base_loc.value, 0, cond=fcond)
return fcond
- def _genop_getinteriorfield(self, op, arglocs, regalloc, fcond):
- (base_loc, index_loc, res_loc,
- ofs_loc, ofs, itemsize, fieldsize) = arglocs
- scale = get_scale(fieldsize.value)
- tmploc, save = self.get_tmp_reg([base_loc, ofs_loc])
- assert not save
- self.mc.gen_load_int(tmploc.value, itemsize.value)
- self.mc.MUL(tmploc.value, index_loc.value, tmploc.value)
- descr = op.getdescr()
- assert isinstance(descr, InteriorFieldDescr)
- signed = descr.fielddescr.is_field_signed()
- if ofs.value > 0:
- if ofs_loc.is_imm():
- self.mc.ADD_ri(tmploc.value, tmploc.value, ofs_loc.value)
- else:
- self.mc.ADD_rr(tmploc.value, tmploc.value, ofs_loc.value)
- ofs_loc = tmploc
- self._load_from_mem(res_loc, base_loc, ofs_loc,
- imm(scale), signed, fcond)
- return fcond
-
- emit_op_getinteriorfield_gc_i = _genop_getinteriorfield
- emit_op_getinteriorfield_gc_r = _genop_getinteriorfield
- emit_op_getinteriorfield_gc_f = _genop_getinteriorfield
-
- def emit_op_setinteriorfield_gc(self, op, arglocs, regalloc, fcond):
- (base_loc, index_loc, value_loc,
- ofs_loc, ofs, itemsize, fieldsize) = arglocs
- scale = get_scale(fieldsize.value)
- tmploc, save = self.get_tmp_reg([base_loc, index_loc, value_loc, ofs_loc])
- assert not save
- self.mc.gen_load_int(tmploc.value, itemsize.value)
- self.mc.MUL(tmploc.value, index_loc.value, tmploc.value)
- if ofs.value > 0:
- if ofs_loc.is_imm():
- self.mc.ADD_ri(tmploc.value, tmploc.value, ofs_loc.value)
- else:
- self.mc.ADD_rr(tmploc.value, tmploc.value, ofs_loc.value)
- self._write_to_mem(value_loc, base_loc, tmploc, imm(scale), fcond)
- return fcond
- emit_op_setinteriorfield_raw = emit_op_setinteriorfield_gc
-
- def emit_op_arraylen_gc(self, op, arglocs, regalloc, fcond):
- res, base_loc, ofs = arglocs
- self.load_reg(self.mc, res, base_loc, ofs.value)
- return fcond
-
- def emit_op_setarrayitem_gc(self, op, arglocs, regalloc, fcond):
- value_loc, base_loc, ofs_loc, scale, ofs = arglocs
- assert ofs_loc.is_core_reg()
- if scale.value > 0:
- self.mc.LSL_ri(r.ip.value, ofs_loc.value, scale.value)
- ofs_loc = r.ip
-
+ def emit_op_gc_store_indexed(self, op, arglocs, regalloc, fcond):
+ value_loc, base_loc, index_loc, size_loc, ofs_loc = arglocs
+ assert index_loc.is_core_reg()
# add the base offset
- if ofs.value > 0:
- self.mc.ADD_ri(r.ip.value, ofs_loc.value, imm=ofs.value)
- ofs_loc = r.ip
- self._write_to_mem(value_loc, base_loc, ofs_loc, scale, fcond)
+ if ofs_loc.value > 0:
+ self.mc.ADD_ri(r.ip.value, index_loc.value, imm=ofs_loc.value)
+ index_loc = r.ip
+ scale = get_scale(size_loc.value)
+ self._write_to_mem(value_loc, base_loc, index_loc, imm(scale), fcond)
return fcond
def _write_to_mem(self, value_loc, base_loc, ofs_loc, scale, fcond=c.AL):
+ # Write a value of size '1 << scale' at the address
+ # 'base_ofs + ofs_loc'. Note that 'scale' is not used to scale
+ # the offset!
if scale.value == 3:
assert value_loc.is_vfp_reg()
# vstr only supports imm offsets
@@ -789,43 +734,31 @@
else:
assert 0
- emit_op_setarrayitem_raw = emit_op_setarrayitem_gc
-
- def emit_op_raw_store(self, op, arglocs, regalloc, fcond):
- value_loc, base_loc, ofs_loc, scale, ofs = arglocs
- assert ofs_loc.is_core_reg()
- self._write_to_mem(value_loc, base_loc, ofs_loc, scale, fcond)
+ def _emit_op_gc_load_indexed(self, op, arglocs, regalloc, fcond):
+ res_loc, base_loc, index_loc, nsize_loc, ofs_loc = arglocs
+ assert index_loc.is_core_reg()
+ nsize = nsize_loc.value
+ signed = (nsize < 0)
+ # add the base offset
+ if ofs_loc.value > 0:
+ self.mc.ADD_ri(r.ip.value, index_loc.value, imm=ofs_loc.value)
+ index_loc = r.ip
+ #
+ scale = get_scale(abs(nsize))
+ self._load_from_mem(res_loc, base_loc, index_loc, imm(scale),
+ signed, fcond)
return fcond
- def _genop_getarrayitem(self, op, arglocs, regalloc, fcond):
- res_loc, base_loc, ofs_loc, scale, ofs = arglocs
- assert ofs_loc.is_core_reg()
- signed = op.getdescr().is_item_signed()
-
- # scale the offset as required
- # XXX we should try to encode the scale inside the "shift" part of LDR
- if scale.value > 0:
- self.mc.LSL_ri(r.ip.value, ofs_loc.value, scale.value)
- ofs_loc = r.ip
- # add the base offset
- if ofs.value > 0:
- self.mc.ADD_ri(r.ip.value, ofs_loc.value, imm=ofs.value)
- ofs_loc = r.ip
- #
- self._load_from_mem(res_loc, base_loc, ofs_loc, scale, signed, fcond)
- return fcond
-
- emit_op_getarrayitem_gc_i = _genop_getarrayitem
- emit_op_getarrayitem_gc_r = _genop_getarrayitem
- emit_op_getarrayitem_gc_f = _genop_getarrayitem
- emit_op_getarrayitem_gc_pure_i = _genop_getarrayitem
- emit_op_getarrayitem_gc_pure_r = _genop_getarrayitem
- emit_op_getarrayitem_gc_pure_f = _genop_getarrayitem
- emit_op_getarrayitem_raw_i = _genop_getarrayitem
- emit_op_getarrayitem_raw_f = _genop_getarrayitem
+ emit_op_gc_load_indexed_i = _emit_op_gc_load_indexed
+ emit_op_gc_load_indexed_r = _emit_op_gc_load_indexed
+ emit_op_gc_load_indexed_f = _emit_op_gc_load_indexed
def _load_from_mem(self, res_loc, base_loc, ofs_loc, scale,
signed=False, fcond=c.AL):
+ # Load a value of '1 << scale' bytes, from the memory location
+ # 'base_loc + ofs_loc'. Note that 'scale' is not used to scale
+ # the offset!
+ #
if scale.value == 3:
assert res_loc.is_vfp_reg()
# vldr only supports imm offsets
@@ -881,51 +814,6 @@
else:
assert 0
- def _genop_raw_load(self, op, arglocs, regalloc, fcond):
- res_loc, base_loc, ofs_loc, scale, ofs = arglocs
- assert ofs_loc.is_core_reg()
- # no base offset
- assert ofs.value == 0
- signed = op.getdescr().is_item_signed()
- self._load_from_mem(res_loc, base_loc, ofs_loc, scale, signed, fcond)
- return fcond
-
- emit_op_raw_load_i = _genop_raw_load
- emit_op_raw_load_f = _genop_raw_load
-
- def emit_op_strlen(self, op, arglocs, regalloc, fcond):
- l0, l1, res = arglocs
- if l1.is_imm():
- self.mc.LDR_ri(res.value, l0.value, l1.getint(), cond=fcond)
- else:
- self.mc.LDR_rr(res.value, l0.value, l1.value, cond=fcond)
- return fcond
-
- def emit_op_strgetitem(self, op, arglocs, regalloc, fcond):
- res, base_loc, ofs_loc, basesize = arglocs
- if ofs_loc.is_imm():
- self.mc.ADD_ri(r.ip.value, base_loc.value, ofs_loc.getint(),
- cond=fcond)
- else:
- self.mc.ADD_rr(r.ip.value, base_loc.value, ofs_loc.value,
- cond=fcond)
-
- self.mc.LDRB_ri(res.value, r.ip.value, basesize.value, cond=fcond)
- return fcond
-
- def emit_op_strsetitem(self, op, arglocs, regalloc, fcond):
- value_loc, base_loc, ofs_loc, basesize = arglocs
- if ofs_loc.is_imm():
- self.mc.ADD_ri(r.ip.value, base_loc.value, ofs_loc.getint(),
- cond=fcond)
- else:
- self.mc.ADD_rr(r.ip.value, base_loc.value, ofs_loc.value,
- cond=fcond)
-
- self.mc.STRB_ri(value_loc.value, r.ip.value, basesize.value,
- cond=fcond)
- return fcond
-
#from ../x86/regalloc.py:928 ff.
def emit_op_copystrcontent(self, op, arglocs, regalloc, fcond):
assert len(arglocs) == 0
@@ -1016,35 +904,6 @@
else:
raise AssertionError("bad unicode item size")
- emit_op_unicodelen = emit_op_strlen
-
- def emit_op_unicodegetitem(self, op, arglocs, regalloc, fcond):
- res, base_loc, ofs_loc, scale, basesize, itemsize = arglocs
- self.mc.ADD_rr(r.ip.value, base_loc.value, ofs_loc.value, cond=fcond,
- imm=scale.value, shifttype=shift.LSL)
- if scale.value == 2:
- self.mc.LDR_ri(res.value, r.ip.value, basesize.value, cond=fcond)
- elif scale.value == 1:
- self.mc.LDRH_ri(res.value, r.ip.value, basesize.value, cond=fcond)
- else:
- assert 0, itemsize.value
- return fcond
-
- def emit_op_unicodesetitem(self, op, arglocs, regalloc, fcond):
- value_loc, base_loc, ofs_loc, scale, basesize, itemsize = arglocs
- self.mc.ADD_rr(r.ip.value, base_loc.value, ofs_loc.value, cond=fcond,
- imm=scale.value, shifttype=shift.LSL)
- if scale.value == 2:
- self.mc.STR_ri(value_loc.value, r.ip.value, basesize.value,
- cond=fcond)
- elif scale.value == 1:
- self.mc.STRH_ri(value_loc.value, r.ip.value, basesize.value,
- cond=fcond)
- else:
- assert 0, itemsize.value
-
- return fcond
-
def store_force_descr(self, op, fail_locs, frame_depth):
pos = self.mc.currpos()
guard_token = self.build_guard_token(op, frame_depth, fail_locs, pos, c.AL)
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
@@ -34,9 +34,6 @@
from rpython.rtyper.lltypesystem import lltype, rffi, rstr, llmemory
from rpython.rtyper.lltypesystem.lloperation import llop
from rpython.jit.codewriter.effectinfo import EffectInfo
-from rpython.jit.backend.llsupport.descr import unpack_arraydescr
-from rpython.jit.backend.llsupport.descr import unpack_fielddescr
-from rpython.jit.backend.llsupport.descr import unpack_interiorfielddescr
from rpython.rlib.rarithmetic import r_uint
from rpython.jit.backend.llsupport.descr import CallDescr
@@ -802,15 +799,12 @@
src_locations2, dst_locations2, vfptmploc)
return []
- def prepare_op_setfield_gc(self, op, fcond):
+ def prepare_op_gc_store(self, op, fcond):
boxes = op.getarglist()
- ofs, size, sign = unpack_fielddescr(op.getdescr())
- return self._prepare_op_setfield(boxes, ofs, size)
-
- def _prepare_op_setfield(self, boxes, ofs, size):
- a0, a1 = boxes
- base_loc = self.make_sure_var_in_reg(a0, boxes)
- value_loc = self.make_sure_var_in_reg(a1, boxes)
+ base_loc = self.make_sure_var_in_reg(boxes[0], boxes)
+ ofs = boxes[1].getint()
+ value_loc = self.make_sure_var_in_reg(boxes[2], boxes)
+ size = abs(boxes[3].getint())
ofs_size = default_imm_size if size < 8 else VMEM_imm_size
if check_imm_arg(ofs, size=ofs_size):
ofs_loc = imm(ofs)
@@ -819,19 +813,13 @@
self.assembler.load(ofs_loc, imm(ofs))
return [value_loc, base_loc, ofs_loc, imm(size)]
- prepare_op_setfield_raw = prepare_op_setfield_gc
-
- def prepare_op_zero_ptr_field(self, op, fcond):
+ def _prepare_op_gc_load(self, op, fcond):
a0 = op.getarg(0)
ofs = op.getarg(1).getint()
- return self._prepare_op_setfield([a0, ConstInt(0)], ofs, WORD)
-
- def _prepare_op_getfield(self, op, fcond):
- a0 = op.getarg(0)
More information about the pypy-commit
mailing list