[pypy-commit] pypy py3.3: hg merge py3k
mjacob
noreply at buildbot.pypy.org
Wed Feb 25 19:07:49 CET 2015
Author: Manuel Jacob <me at manueljacob.de>
Branch: py3.3
Changeset: r76146:61760b499e7c
Date: 2015-02-25 18:00 +0100
http://bitbucket.org/pypy/pypy/changeset/61760b499e7c/
Log: hg merge py3k
diff too long, truncating to 2000 out of 3992 lines
diff --git a/lib_pypy/_gdbm.py b/lib_pypy/_gdbm.py
--- a/lib_pypy/_gdbm.py
+++ b/lib_pypy/_gdbm.py
@@ -20,9 +20,11 @@
} datum;
datum gdbm_fetch(void*, datum);
+datum pygdbm_fetch(void*, char*, int);
int gdbm_delete(void*, datum);
int gdbm_store(void*, datum, datum, int);
int gdbm_exists(void*, datum);
+int pygdbm_exists(void*, char*, int);
int gdbm_reorganize(void*);
@@ -37,19 +39,29 @@
''')
try:
+ verify_code = '''
+ #include "gdbm.h"
+
+ static datum pygdbm_fetch(GDBM_FILE gdbm_file, char *dptr, int dsize) {
+ datum key = {dptr, dsize};
+ return gdbm_fetch(gdbm_file, key);
+ }
+
+ static int pygdbm_exists(GDBM_FILE gdbm_file, char *dptr, int dsize) {
+ datum key = {dptr, dsize};
+ return gdbm_exists(gdbm_file, key);
+ }
+
+ '''
if sys.platform.startswith('freebsd'):
import os.path
_localbase = os.environ.get('LOCALBASE', '/usr/local')
- lib = ffi.verify('''
- #include "gdbm.h"
- ''', libraries=['gdbm'],
+ lib = ffi.verify(verify_code, libraries=['gdbm'],
include_dirs=[os.path.join(_localbase, 'include')],
library_dirs=[os.path.join(_localbase, 'lib')]
)
else:
- lib = ffi.verify('''
- #include "gdbm.h"
- ''', libraries=['gdbm'])
+ lib = ffi.verify(verify_code, libraries=['gdbm'])
except cffi.VerificationError as e:
# distutils does not preserve the actual message,
# but the verification is simple enough that the
@@ -59,6 +71,13 @@
class error(IOError):
pass
+def _checkstr(key):
+ if isinstance(key, str):
+ key = key.encode("ascii")
+ if not isinstance(key, bytes):
+ raise TypeError("gdbm mappings have string indices only")
+ return key
+
def _fromstr(key):
if isinstance(key, str):
key = key.encode(sys.getdefaultencoding())
@@ -108,12 +127,14 @@
def __contains__(self, key):
self._check_closed()
- return lib.gdbm_exists(self.ll_dbm, _fromstr(key))
+ key = _checkstr(key)
+ return lib.pygdbm_exists(self.ll_dbm, key, len(key))
has_key = __contains__
def get(self, key, default=None):
self._check_closed()
- drec = lib.gdbm_fetch(self.ll_dbm, _fromstr(key))
+ key = _checkstr(key)
+ drec = lib.pygdbm_fetch(self.ll_dbm, key, len(key))
if not drec.dptr:
return default
res = bytes(ffi.buffer(drec.dptr, drec.dsize))
diff --git a/pypy/doc/embedding.rst b/pypy/doc/embedding.rst
--- a/pypy/doc/embedding.rst
+++ b/pypy/doc/embedding.rst
@@ -36,7 +36,8 @@
"PyPy home directory". The arguments are:
* ``home``: NULL terminated path to an executable inside the pypy directory
- (can be a .so name, can be made up)
+ (can be a .so name, can be made up). Used to look up the standard
+ library, and is also set as ``sys.executable``.
* ``verbose``: if non-zero, it will print error messages to stderr
diff --git a/pypy/doc/test/test_whatsnew.py b/pypy/doc/test/test_whatsnew.py
--- a/pypy/doc/test/test_whatsnew.py
+++ b/pypy/doc/test/test_whatsnew.py
@@ -85,7 +85,7 @@
#whatsnew_list = doc.listdir('whatsnew-*.rst')
#whatsnew_list.sort()
#last_whatsnew = whatsnew_list[-1].read()
- last_whatsnew = doc.join('whatsnew-head.rst').read()
+ last_whatsnew = doc.join('whatsnew-pypy3-head.rst').read()
startrev, documented = parse_doc(last_whatsnew)
merged, branch = get_merged_branches(ROOT, startrev, '')
merged.discard('default')
@@ -100,5 +100,5 @@
print '\n'.join(not_merged)
print
assert not not_documented
- if branch == 'default':
+ if branch == 'py3k':
assert not not_merged
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
@@ -6,8 +6,8 @@
.. startrev: 397b96217b85
-Fix non-blocking file reads sometimes raising EAGAIN even though they
-have buffered data waiting (b1c4fcb04a42)
+Non-blocking file reads sometimes raised EAGAIN even though they
+had buffered data waiting, fixed in b1c4fcb04a42
.. branch: vmprof
@@ -18,3 +18,19 @@
.. branch: stdlib-2.7.9
Update stdlib to version 2.7.9
+
+.. branch: fix-kqueue-error2
+Fix exception being raised by kqueue.control (CPython compatibility)
+
+.. branch: gitignore
+
+.. branch: framestate2
+Refactor rpython.flowspace.framestate.FrameState.
+
+.. branch: alt_errno
+Add an alternative location to save LastError, errno around ctypes,
+cffi external calls so things like pdb will not overwrite it
+
+.. branch: nonquadratic-heapcache
+Speed up the warmup times of the JIT by removing a quadratic algorithm in the
+heapcache.
diff --git a/pypy/doc/whatsnew-pypy3-head.rst b/pypy/doc/whatsnew-pypy3-head.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/whatsnew-pypy3-head.rst
@@ -0,0 +1,10 @@
+========================
+What's new in PyPy3 2.4+
+========================
+
+.. this is the revision after pypy3-release-2.4.x was branched
+.. startrev: 3f967c2be00e
+
+.. branch: py3k-memoryview
+
+Implement new memoryview features.
diff --git a/pypy/goal/targetpypystandalone.py b/pypy/goal/targetpypystandalone.py
--- a/pypy/goal/targetpypystandalone.py
+++ b/pypy/goal/targetpypystandalone.py
@@ -113,6 +113,9 @@
space.call_function(w_pathsetter, w_path)
# import site
try:
+ space.setattr(space.getbuiltinmodule('sys'),
+ space.wrap('executable'),
+ space.wrap(home))
import_ = space.getattr(space.getbuiltinmodule('builtins'),
space.wrap('__import__'))
space.call_function(import_, space.wrap('site'))
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
@@ -1,5 +1,5 @@
#! /usr/bin/env python
-# App-level version of py.py.
+# This is pure Python code that handles the main entry point into "pypy".
# See test/test_app_main.
# Missing vs CPython: -b, -d, -v, -x, -3
@@ -158,11 +158,14 @@
current = group
raise SystemExit
+def get_sys_executable():
+ return getattr(sys, 'executable', 'pypy')
+
def print_help(*args):
import os
initstdio()
print('usage: %s [option] ... [-c cmd | -m mod | file | -] [arg] ...' % (
- sys.executable,))
+ get_sys_executable(),))
print(USAGE1, end='')
if 'pypyjit' in sys.builtin_module_names:
print("--jit options: advanced JIT options: try 'off' or 'help'")
@@ -174,7 +177,7 @@
try:
import pypyjit
except ImportError:
- print("No jit support in %s" % (sys.executable,), file=sys.stderr)
+ print("No jit support in %s" % (get_sys_executable(),), file=sys.stderr)
return
items = sorted(pypyjit.defaults.items())
print('Advanced JIT options: a comma-separated list of OPTION=VALUE:')
@@ -213,7 +216,7 @@
raise SystemExit
if 'pypyjit' not in sys.builtin_module_names:
initstdio()
- print("Warning: No jit support in %s" % (sys.executable,),
+ print("Warning: No jit support in %s" % (get_sys_executable(),),
file=sys.stderr)
else:
import pypyjit
@@ -224,8 +227,8 @@
def print_error(msg):
print(msg, file=sys.stderr)
- print('usage: %s [options]' % (sys.executable,), file=sys.stderr)
- print('Try `%s -h` for more information.' % (sys.executable,), file=sys.stderr)
+ print('usage: %s [options]' % (get_sys_executable(),), file=sys.stderr)
+ print('Try `%s -h` for more information.' % (get_sys_executable(),), file=sys.stderr)
def fdopen(fd, mode, bufsize=-1):
try:
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -25,6 +25,29 @@
reds=['items', 'w_iterator'])
+# It seems there's no way to do it without top-level-functions.
+
+ at specialize.memo()
+def _does_override_buffer_w(type):
+ return type.buffer_w != W_Root.buffer_w
+
+ at specialize.memo()
+def _does_override_buffer_w_ex(type):
+ return type.buffer_w_ex != W_Root.buffer_w_ex
+
+ at specialize.argtype(0)
+def W_Root_buffer_w(self, space, flags):
+ if _does_override_buffer_w_ex(self.__class__):
+ return self.buffer_w_ex(space, flags)[0]
+ return self._buffer(space, flags).buffer_w(space, flags)
+
+ at specialize.argtype(0)
+def W_Root_buffer_w_ex(self, space, flags):
+ if _does_override_buffer_w(self.__class__):
+ return self.buffer_w(space, flags), 'B', 1
+ return self._buffer(space, flags).buffer_w_ex(space, flags)
+
+
class W_Root(object):
"""This is the abstract root class of all wrapped objects that live
in a 'normal' object space like StdObjSpace."""
@@ -195,11 +218,17 @@
return None
def buffer_w(self, space, flags):
+ return W_Root_buffer_w(self, space, flags)
+
+ def buffer_w_ex(self, space, flags):
+ return W_Root_buffer_w_ex(self, space, flags)
+
+ def _buffer(self, space, flags):
w_impl = space.lookup(self, '__buffer__')
if w_impl is not None:
w_result = space.get_and_call_function(w_impl, self)
if space.isinstance_w(w_result, space.w_memoryview):
- return w_result.buffer_w(space, flags)
+ return w_result
raise TypeError
def bytes_w(self, space):
@@ -1379,6 +1408,15 @@
raise oefmt(self.w_TypeError,
"'%T' does not support the buffer interface", w_obj)
+ def buffer_w_ex(self, w_obj, flags):
+ # New buffer interface, returns a buffer based on flags (PyObject_GetBuffer)
+ # Returns extra information: (buffer, typecode, itemsize)
+ try:
+ return w_obj.buffer_w_ex(self, flags)
+ except TypeError:
+ raise oefmt(self.w_TypeError,
+ "'%T' does not support the buffer interface", w_obj)
+
def readbuf_w(self, w_obj):
# Old buffer interface, returns a readonly buffer (PyObject_AsReadBuffer)
try:
diff --git a/pypy/interpreter/test/test_objspace.py b/pypy/interpreter/test/test_objspace.py
--- a/pypy/interpreter/test/test_objspace.py
+++ b/pypy/interpreter/test/test_objspace.py
@@ -404,7 +404,7 @@
config = make_config(None)
space = make_objspace(config)
w_executable = space.wrap('executable')
- assert space.str_w(space.getattr(space.sys, w_executable)) == 'py.py'
+ assert space.findattr(space.sys, w_executable) is None
space.setattr(space.sys, w_executable, space.wrap('foobar'))
assert space.str_w(space.getattr(space.sys, w_executable)) == 'foobar'
space.startup()
diff --git a/pypy/interpreter/test/test_targetpypy.py b/pypy/interpreter/test/test_targetpypy.py
--- a/pypy/interpreter/test/test_targetpypy.py
+++ b/pypy/interpreter/test/test_targetpypy.py
@@ -8,7 +8,7 @@
entry_point = get_entry_point(config)[0]
entry_point(['pypy-c' , '-S', '-c', 'print 3'])
-def test_exeucte_source(space):
+def test_execute_source(space):
_, d = create_entry_point(space, None)
execute_source = d['pypy_execute_source']
lls = rffi.str2charp("import sys; sys.modules['xyz'] = 3")
diff --git a/pypy/module/_cffi_backend/cbuffer.py b/pypy/module/_cffi_backend/cbuffer.py
--- a/pypy/module/_cffi_backend/cbuffer.py
+++ b/pypy/module/_cffi_backend/cbuffer.py
@@ -3,7 +3,6 @@
from pypy.interpreter.gateway import unwrap_spec, interp2app
from pypy.interpreter.typedef import TypeDef, make_weakref_descr
from pypy.module._cffi_backend import cdataobj, ctypeptr, ctypearray
-from pypy.objspace.std.memoryobject import _buffer_setitem
from rpython.rlib.buffer import Buffer
from rpython.rtyper.annlowlevel import llstr
@@ -41,8 +40,6 @@
copy_string_to_raw(llstr(string), raw_cdata, 0, len(string))
-# Override the typedef to narrow down the interface that's exposed to app-level
-
class MiniBuffer(W_Root):
def __init__(self, buffer, keepalive=None):
self.buffer = buffer
@@ -63,7 +60,18 @@
return space.wrapbytes(res)
def descr_setitem(self, space, w_index, w_newstring):
- _buffer_setitem(space, self.buffer, w_index, w_newstring)
+ start, stop, step, size = space.decode_index4(w_index,
+ self.buffer.getlength())
+ if step not in (0, 1):
+ raise oefmt(space.w_NotImplementedError, "")
+ value = space.buffer_w(w_newstring, space.BUF_CONTIG_RO)
+ if value.getlength() != size:
+ raise oefmt(space.w_ValueError,
+ "cannot modify size of memoryview object")
+ if step == 0: # index only
+ self.buffer.setitem(start, value.getitem(0))
+ elif step == 1:
+ self.buffer.setslice(start, value.as_str())
MiniBuffer.typedef = TypeDef(
diff --git a/pypy/module/_cffi_backend/ccallback.py b/pypy/module/_cffi_backend/ccallback.py
--- a/pypy/module/_cffi_backend/ccallback.py
+++ b/pypy/module/_cffi_backend/ccallback.py
@@ -210,6 +210,6 @@
space.threadlocals.leave_thread(space)
def invoke_callback(ffi_cif, ll_res, ll_args, ll_userdata):
- cerrno._errno_after(rffi.RFFI_ERR_ALL)
+ cerrno._errno_after(rffi.RFFI_ERR_ALL | rffi.RFFI_ALT_ERRNO)
_invoke_callback(ffi_cif, ll_res, ll_args, ll_userdata)
- cerrno._errno_before(rffi.RFFI_ERR_ALL)
+ cerrno._errno_before(rffi.RFFI_ERR_ALL | rffi.RFFI_ALT_ERRNO)
diff --git a/pypy/module/_cffi_backend/cerrno.py b/pypy/module/_cffi_backend/cerrno.py
--- a/pypy/module/_cffi_backend/cerrno.py
+++ b/pypy/module/_cffi_backend/cerrno.py
@@ -13,18 +13,18 @@
_errno_after = rposix._errno_after
def get_errno(space):
- return space.wrap(rposix.get_saved_errno())
+ return space.wrap(rposix.get_saved_alterrno())
@unwrap_spec(errno=int)
def set_errno(space, errno):
- rposix.set_saved_errno(errno)
+ rposix.set_saved_alterrno(errno)
# ____________________________________________________________
@unwrap_spec(code=int)
def getwinerror(space, code=-1):
- from rpython.rlib.rwin32 import GetLastError_saved, FormatError
+ from rpython.rlib.rwin32 import GetLastError_alt_saved, FormatError
if code == -1:
- code = GetLastError_saved()
+ code = GetLastError_alt_saved()
message = FormatError(code)
return space.newtuple([space.wrap(code), space.wrap(message)])
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
@@ -2716,6 +2716,14 @@
assert data == b"Xhello\n"
posix.close(fdr)
+def test_errno_saved():
+ set_errno(42)
+ # a random function that will reset errno to 0 (at least on non-windows)
+ import os; os.stat('.')
+ #
+ res = get_errno()
+ assert res == 42
+
def test_GetLastError():
if sys.platform != "win32":
py.test.skip("GetLastError(): only for Windows")
diff --git a/pypy/module/_rawffi/array.py b/pypy/module/_rawffi/array.py
--- a/pypy/module/_rawffi/array.py
+++ b/pypy/module/_rawffi/array.py
@@ -15,7 +15,7 @@
from pypy.module._rawffi.interp_rawffi import unpack_shape_with_length
from pypy.module._rawffi.interp_rawffi import read_ptr, write_ptr
from rpython.rlib.rarithmetic import r_uint
-from rpython.rlib import rgc
+from rpython.rlib import rgc, clibffi
class W_Array(W_DataShape):
@@ -84,14 +84,11 @@
class W_ArrayInstance(W_DataInstance):
def __init__(self, space, shape, length, address=r_uint(0)):
- # Workaround for a strange behavior of libffi: make sure that
- # we always have at least 8 bytes. For W_ArrayInstances that are
- # used as the result value of a function call, ffi_call() writes
- # 8 bytes into it even if the function's result type asks for less.
- # This strange behavior is documented.
memsize = shape.size * length
- if memsize < 8:
- memsize = 8
+ # For W_ArrayInstances that are used as the result value of a
+ # function call, ffi_call() writes 8 bytes into it even if the
+ # function's result type asks for less.
+ memsize = clibffi.adjust_return_size(memsize)
W_DataInstance.__init__(self, space, memsize, address)
self.length = length
self.shape = shape
diff --git a/pypy/module/_rawffi/interp_rawffi.py b/pypy/module/_rawffi/interp_rawffi.py
--- a/pypy/module/_rawffi/interp_rawffi.py
+++ b/pypy/module/_rawffi/interp_rawffi.py
@@ -498,6 +498,7 @@
try:
if self.resshape is not None:
result = self.resshape.allocate(space, 1, autofree=True)
+ # adjust_return_size() was used here on result.ll_buffer
self.ptr.call(args_ll, result.ll_buffer)
return space.wrap(result)
else:
@@ -611,19 +612,19 @@
return space.wrap(W_CDLL(space, name, cdll))
def get_errno(space):
- return space.wrap(rposix.get_saved_errno())
+ return space.wrap(rposix.get_saved_alterrno())
def set_errno(space, w_errno):
- rposix.set_saved_errno(space.int_w(w_errno))
+ rposix.set_saved_alterrno(space.int_w(w_errno))
if sys.platform == 'win32':
# see also
# https://bitbucket.org/pypy/pypy/issue/1944/ctypes-on-windows-getlasterror
def get_last_error(space):
- return space.wrap(rwin32.GetLastError_saved())
+ return space.wrap(rwin32.GetLastError_alt_saved())
@unwrap_spec(error=int)
def set_last_error(space, error):
- rwin32.SetLastError_saved(error)
+ rwin32.SetLastError_alt_saved(error)
else:
# always have at least a dummy version of these functions
# (https://bugs.pypy.org/issue1242)
diff --git a/pypy/module/_ssl/interp_ssl.py b/pypy/module/_ssl/interp_ssl.py
--- a/pypy/module/_ssl/interp_ssl.py
+++ b/pypy/module/_ssl/interp_ssl.py
@@ -4,6 +4,7 @@
from rpython.rlib.rarithmetic import intmask, widen, r_uint
from rpython.rlib import rpoll, rsocket, rthread, rweakref
from rpython.rlib.ropenssl import *
+from rpython.rlib._rsocket_rffi import MAX_FD_SIZE
from rpython.rlib.rposix import get_saved_errno
from rpython.rlib.rweakref import RWeakValueDictionary
from rpython.rlib.objectmodel import specialize, compute_unique_id
diff --git a/pypy/module/_ssl/test/test_ssl.py b/pypy/module/_ssl/test/test_ssl.py
--- a/pypy/module/_ssl/test/test_ssl.py
+++ b/pypy/module/_ssl/test/test_ssl.py
@@ -236,6 +236,9 @@
def test_npn_protocol(self):
import socket, _ssl, gc
+ if not _ssl.HAS_NPN:
+ skip("NPN requires OpenSSL 1.0.1 or greater")
+
ctx = _ssl._SSLContext()
ctx._set_npn_protocols(b'\x08http/1.1\x06spdy/2')
ss = ctx._wrap_socket(self.s, True,
@@ -306,12 +309,13 @@
os.path.dirname(__file__), 'dh512.pem'))
def test_load_cert_chain(self):
- import _ssl
+ import _ssl, errno
ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLSv1)
ctx.load_cert_chain(self.keycert)
ctx.load_cert_chain(self.cert, self.key)
- raises(IOError, ctx.load_cert_chain, "inexistent.pem")
- raises(_ssl.SSLError, ctx.load_cert_chain, self.badcert)
+ exc = raises(IOError, ctx.load_cert_chain, "inexistent.pem")
+ assert exc.value.errno == errno.ENOENT
+ exc = raises(_ssl.SSLError, ctx.load_cert_chain, self.badcert)
raises(_ssl.SSLError, ctx.load_cert_chain, self.emptycert)
# Password protected key and cert
raises(_ssl.SSLError, ctx.load_cert_chain, self.cert_protected,
@@ -370,12 +374,14 @@
assert ctx.cert_store_stats() == {'x509_ca': 0, 'crl': 0, 'x509': 1}
def test_load_dh_params(self):
- import _ssl
+ import _ssl, errno
ctx = _ssl._SSLContext(_ssl.PROTOCOL_TLSv1)
ctx.load_dh_params(self.dh512)
raises(TypeError, ctx.load_dh_params)
raises(TypeError, ctx.load_dh_params, None)
raises(_ssl.SSLError, ctx.load_dh_params, self.keycert)
+ exc = raises(IOError, ctx.load_dh_params, "inexistent.pem")
+ assert exc.value.errno == errno.ENOENT
def test_set_ecdh_curve(self):
import _ssl
diff --git a/pypy/module/array/interp_array.py b/pypy/module/array/interp_array.py
--- a/pypy/module/array/interp_array.py
+++ b/pypy/module/array/interp_array.py
@@ -59,10 +59,12 @@
def descr_itemsize(space, self):
+ assert isinstance(self, W_ArrayBase)
return space.wrap(self.itemsize)
def descr_typecode(space, self):
+ assert isinstance(self, W_ArrayBase)
return space.wrap(self.typecode)
arr_eq_driver = jit.JitDriver(name='array_eq_driver', greens=['comp_func'],
@@ -135,8 +137,8 @@
self.len = 0
self.allocated = 0
- def buffer_w(self, space, flags):
- return ArrayBuffer(self, False)
+ def buffer_w_ex(self, space, flags):
+ return ArrayBuffer(self, False), self.typecode, self.itemsize
def descr_append(self, space, w_x):
""" append(x)
diff --git a/pypy/module/array/test/test_array.py b/pypy/module/array/test/test_array.py
--- a/pypy/module/array/test/test_array.py
+++ b/pypy/module/array/test/test_array.py
@@ -413,7 +413,16 @@
def test_buffer(self):
a = self.array('h', b'Hi')
buf = memoryview(a)
- assert buf[1] == ord('i')
+ assert buf[0] == 26952
+ raises(IndexError, 'buf[1]')
+ assert buf.tobytes() == b'Hi'
+ assert buf.tolist() == [26952]
+ assert buf.format == 'h'
+ assert buf.itemsize == 2
+ assert buf.shape == (1,)
+ assert buf.ndim == 1
+ assert buf.strides == (2,)
+ assert not buf.readonly
def test_buffer_write(self):
a = self.array('b', b'hello')
@@ -433,6 +442,11 @@
a.fromstring(b'some extra text')
assert buf[:] == b'foobarbazsome extra text'
+ def test_memview_multi_tobytes(self):
+ a = self.array('i', list(b"abcdef"))
+ m = memoryview(a)
+ assert m.tobytes() == a.tobytes()
+
def test_list_methods(self):
assert repr(self.array('i')) == "array('i')"
assert repr(self.array('i', [1, 2, 3])) == "array('i', [1, 2, 3])"
diff --git a/pypy/module/cpyext/bytesobject.py b/pypy/module/cpyext/bytesobject.py
--- a/pypy/module/cpyext/bytesobject.py
+++ b/pypy/module/cpyext/bytesobject.py
@@ -255,5 +255,3 @@
return w_obj
buffer = space.buffer_w(w_obj, space.BUF_FULL_RO)
return space.wrapbytes(buffer.as_str())
-
-
diff --git a/pypy/module/cpyext/include/patchlevel.h b/pypy/module/cpyext/include/patchlevel.h
--- a/pypy/module/cpyext/include/patchlevel.h
+++ b/pypy/module/cpyext/include/patchlevel.h
@@ -29,7 +29,7 @@
#define PY_VERSION "3.3.5"
/* PyPy version as a string */
-#define PYPY_VERSION "2.6.0"
+#define PYPY_VERSION "2.6.0-alpha0"
/* Subversion Revision number of this file (not of the repository).
* Empty since Mercurial migration. */
diff --git a/pypy/module/micronumpy/ndarray.py b/pypy/module/micronumpy/ndarray.py
--- a/pypy/module/micronumpy/ndarray.py
+++ b/pypy/module/micronumpy/ndarray.py
@@ -633,6 +633,7 @@
"ctypes not implemented yet"))
def buffer_w(self, space, flags):
+ # XXX format isn't always 'B' probably
return self.implementation.get_buffer(space, True)
def descr_get_data(self, space):
diff --git a/pypy/module/pypyjit/test_pypy_c/test_ffi.py b/pypy/module/pypyjit/test_pypy_c/test_ffi.py
--- a/pypy/module/pypyjit/test_pypy_c/test_ffi.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_ffi.py
@@ -202,7 +202,7 @@
assert loop.match_by_id('cfficall', """
p96 = force_token()
setfield_gc(p0, p96, descr=<FieldP pypy.interpreter.pyframe.PyFrame.vable_token .>)
- f97 = call_release_gil(27, i59, 1.0, 3, descr=<Callf 8 fi EF=6 OS=62>)
+ f97 = call_release_gil(91, i59, 1.0, 3, descr=<Callf 8 fi EF=6 OS=62>)
guard_not_forced(descr=...)
guard_no_exception(descr=...)
""", ignore_ops=['guard_not_invalidated'])
diff --git a/pypy/module/pypyjit/test_pypy_c/test_thread.py b/pypy/module/pypyjit/test_pypy_c/test_thread.py
--- a/pypy/module/pypyjit/test_pypy_c/test_thread.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_thread.py
@@ -67,21 +67,10 @@
i58 = call_release_gil(0, _, i37, 1, descr=<Calli 4 ii EF=6>)
guard_not_forced(descr=...)
guard_no_exception(descr=...)
- i59 = int_is_true(i58)
- guard_true(i59, descr=...)
- i60 = int_sub(i44, 1)
- p62 = force_token()
- setfield_gc(p0, p62, descr=<FieldP pypy.interpreter.pyframe.PyFrame.vable_token 8>)
- i63 = call_release_gil(0, _, i37, 0, descr=<Calli 4 ii EF=6>)
- guard_not_forced(descr=...)
- guard_no_exception(descr=...)
- i64 = int_is_true(i63)
- guard_false(i64, descr=...)
- p65 = force_token()
- setfield_gc(p0, p65, descr=<FieldP pypy.interpreter.pyframe.PyFrame.vable_token 8>)
- call_release_gil(0, _, i37, descr=<Callv 0 i EF=6>)
- guard_not_forced(descr=...)
- guard_no_exception(descr=...)
+ i58 = int_sub(i44, 1)
+ i59 = call(ConstClass(RPyThreadReleaseLock), i37, descr=<Calli . i EF=2>)
+ i60 = int_is_true(i59)
+ guard_false(i60, descr=...)
guard_not_invalidated(descr=...)
--TICK--
jump(..., descr=...)
diff --git a/pypy/module/sys/__init__.py b/pypy/module/sys/__init__.py
--- a/pypy/module/sys/__init__.py
+++ b/pypy/module/sys/__init__.py
@@ -56,7 +56,6 @@
'getsizeof' : 'vm.getsizeof',
'intern' : 'vm.intern',
- 'executable' : 'space.wrap("py.py")',
'api_version' : 'version.get_api_version(space)',
'version_info' : 'version.get_version_info(space)',
'version' : 'version.get_version(space)',
diff --git a/pypy/module/sys/test/test_sysmodule.py b/pypy/module/sys/test/test_sysmodule.py
--- a/pypy/module/sys/test/test_sysmodule.py
+++ b/pypy/module/sys/test/test_sysmodule.py
@@ -511,7 +511,7 @@
assert isinstance(sys.builtin_module_names, tuple)
assert isinstance(sys.copyright, str)
#assert isinstance(sys.exec_prefix, str) -- not present!
- assert isinstance(sys.executable, str)
+ #assert isinstance(sys.executable, str)
assert isinstance(sys.hexversion, int)
assert isinstance(sys.maxsize, int)
assert isinstance(sys.maxunicode, int)
@@ -565,6 +565,13 @@
raises(AttributeError, "del ns.spam")
del ns.y
+ def test_reload_doesnt_override_sys_executable(self):
+ import sys
+ from imp import reload
+ sys.executable = 'from_test_sysmodule'
+ reload(sys)
+ assert sys.executable == 'from_test_sysmodule'
+
def test_settrace(self):
import sys
counts = []
diff --git a/pypy/module/test_lib_pypy/ctypes_tests/_ctypes_test.c b/pypy/module/test_lib_pypy/ctypes_tests/_ctypes_test.c
--- a/pypy/module/test_lib_pypy/ctypes_tests/_ctypes_test.c
+++ b/pypy/module/test_lib_pypy/ctypes_tests/_ctypes_test.c
@@ -272,7 +272,11 @@
{
double x, sum=0.0, dx=(b-a)/(double)nstep;
for(x=a+0.5*dx; (b-x)*(x-a)>0.0; x+=dx)
+ {
+ double y = f(x);
+ printf("f(x)=%.1f\n", y);
sum += f(x);
+ }
return sum/(double)nstep;
}
diff --git a/pypy/module/test_lib_pypy/ctypes_tests/test_callbacks.py b/pypy/module/test_lib_pypy/ctypes_tests/test_callbacks.py
--- a/pypy/module/test_lib_pypy/ctypes_tests/test_callbacks.py
+++ b/pypy/module/test_lib_pypy/ctypes_tests/test_callbacks.py
@@ -138,6 +138,7 @@
integrate.restype = c_double
def func(x):
+ print 'calculating x**2 of',x
return x**2
result = integrate(0.0, 1.0, CALLBACK(func), 10)
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
@@ -171,7 +171,6 @@
if cConfig.has_gettimeofday:
c_gettimeofday = external('gettimeofday', [rffi.VOIDP, rffi.VOIDP], rffi.INT)
TM_P = lltype.Ptr(tm)
-c_clock = external('clock', [rffi.TIME_TP], clock_t)
c_time = external('time', [rffi.TIME_TP], rffi.TIME_T)
c_gmtime = external('gmtime', [rffi.TIME_TP], TM_P,
save_err=rffi.RFFI_SAVE_ERRNO)
diff --git a/pypy/module/zipimport/interp_zipimport.py b/pypy/module/zipimport/interp_zipimport.py
--- a/pypy/module/zipimport/interp_zipimport.py
+++ b/pypy/module/zipimport/interp_zipimport.py
@@ -199,8 +199,7 @@
magic = importing._get_long(buf[:4])
timestamp = importing._get_long(buf[4:8])
if not self.can_use_pyc(space, filename, magic, timestamp):
- return self.import_py_file(space, modname, filename[:-1], buf,
- pkgpath)
+ return None
buf = buf[8:] # XXX ugly copy, should use sequential read instead
w_mod = w(Module(space, w(modname)))
real_name = self.filename + os.path.sep + self.corr_zname(filename)
@@ -249,7 +248,6 @@
def load_module(self, space, fullname):
w = space.wrap
filename = self.make_filename(fullname)
- last_exc = None
for compiled, is_package, ext in ENUMERATE_EXTS:
fname = filename + ext
try:
@@ -268,19 +266,18 @@
pkgpath = None
try:
if compiled:
- return self.import_pyc_file(space, fullname, fname,
- buf, pkgpath)
+ w_result = self.import_pyc_file(space, fullname, fname,
+ buf, pkgpath)
+ if w_result is not None:
+ return w_result
else:
return self.import_py_file(space, fullname, fname,
buf, pkgpath)
- except OperationError, e:
- last_exc = e
+ except:
w_mods = space.sys.get('modules')
- space.call_method(w_mods, 'pop', w(fullname), space.w_None)
- if last_exc:
- raise OperationError(get_error(space), last_exc.get_w_value(space))
- # should never happen I think
- return space.w_None
+ space.call_method(w_mods, 'pop', w(fullname), space.w_None)
+ raise
+ raise oefmt(get_error(space), "can't find module '%s'", fullname)
@unwrap_spec(filename='str0')
def get_data(self, space, filename):
diff --git a/pypy/module/zipimport/test/test_zipimport.py b/pypy/module/zipimport/test/test_zipimport.py
--- a/pypy/module/zipimport/test/test_zipimport.py
+++ b/pypy/module/zipimport/test/test_zipimport.py
@@ -195,7 +195,8 @@
m0 ^= 0x04
test_pyc = bytes([m0]) + self.get_pyc()[1:]
self.writefile("uu.pyc", test_pyc)
- raises(ImportError, "__import__('uu', globals(), locals(), [])")
+ raises(zipimport.ZipImportError,
+ "__import__('uu', globals(), locals(), [])")
assert 'uu' not in sys.modules
def test_force_py(self):
@@ -386,6 +387,11 @@
finally:
os.remove(filename)
+ def test_import_exception(self):
+ self.writefile('x1test.py', '1/0')
+ self.writefile('x1test/__init__.py', 'raise ValueError')
+ raises(ValueError, __import__, 'x1test', None, None, [])
+
if os.sep != '/':
class AppTestNativePathSep(AppTestZipimport):
diff --git a/pypy/objspace/std/intobject.py b/pypy/objspace/std/intobject.py
--- a/pypy/objspace/std/intobject.py
+++ b/pypy/objspace/std/intobject.py
@@ -567,9 +567,11 @@
def descr_bit_length(self, space):
val = self.intval
+ bits = 0
if val < 0:
- val = -val
- bits = 0
+ # warning, "-val" overflows here
+ val = -((val + 1) >> 1)
+ bits = 1
while val:
bits += 1
val >>= 1
diff --git a/pypy/objspace/std/memoryobject.py b/pypy/objspace/std/memoryobject.py
--- a/pypy/objspace/std/memoryobject.py
+++ b/pypy/objspace/std/memoryobject.py
@@ -11,51 +11,26 @@
from pypy.interpreter.typedef import TypeDef, GetSetProperty, make_weakref_descr
-def _buffer_setitem(space, buf, w_index, w_obj, as_int=False):
- # This function is also used by _cffi_backend, but cffi.buffer()
- # works with single byte characters, whereas memory object uses
- # numbers.
- if buf.readonly:
- raise oefmt(space.w_TypeError, "cannot modify read-only memory")
- start, stop, step, size = space.decode_index4(w_index, buf.getlength())
- if step == 0: # index only
- if as_int:
- value = chr(space.int_w(w_obj))
- else:
- val = space.buffer_w(w_obj, space.BUF_CONTIG_RO)
- if val.getlength() != 1:
- raise oefmt(space.w_ValueError,
- "cannot modify size of memoryview object")
- value = val.getitem(0)
- buf.setitem(start, value)
- elif step == 1:
- value = space.buffer_w(w_obj, space.BUF_CONTIG_RO)
- if value.getlength() != size:
- raise oefmt(space.w_ValueError,
- "cannot modify size of memoryview object")
- buf.setslice(start, value.as_str())
- else:
- raise oefmt(space.w_NotImplementedError, "")
-
-
class W_MemoryView(W_Root):
"""Implement the built-in 'memoryview' type as a wrapper around
an interp-level buffer.
"""
- def __init__(self, buf):
+ def __init__(self, buf, format='B', itemsize=1):
assert isinstance(buf, Buffer)
self.buf = buf
self._hash = -1
+ self.format = format
+ self.itemsize = itemsize
- def buffer_w(self, space, flags):
+ def buffer_w_ex(self, space, flags):
self._check_released(space)
space.check_buf_flags(flags, self.buf.readonly)
- return self.buf
+ return self.buf, self.format, self.itemsize
@staticmethod
def descr_new_memoryview(space, w_subtype, w_object):
- return W_MemoryView(space.buffer_w(w_object, space.BUF_FULL_RO))
+ return W_MemoryView(*space.buffer_w_ex(w_object, space.BUF_FULL_RO))
def _make_descr__cmp(name):
def descr__cmp(self, space, w_other):
@@ -84,10 +59,12 @@
descr_ne = _make_descr__cmp('ne')
def as_str(self):
- return self.buf.as_str()
+ buf = self.buf
+ n_bytes = buf.getlength()
+ return buf.getslice(0, n_bytes, 1, n_bytes)
def getlength(self):
- return self.buf.getlength()
+ return self.buf.getlength() // self.itemsize
def descr_tobytes(self, space):
self._check_released(space)
@@ -96,37 +73,53 @@
def descr_tolist(self, space):
self._check_released(space)
buf = self.buf
+ if self.format != 'B':
+ raise oefmt(space.w_NotImplementedError,
+ "tolist() only supports byte views")
result = []
for i in range(buf.getlength()):
- result.append(space.wrap(ord(buf.getitem(i))))
+ result.append(space.wrap(ord(buf.getitem(i)[0])))
return space.newlist(result)
def descr_getitem(self, space, w_index):
self._check_released(space)
start, stop, step, size = space.decode_index4(w_index, self.getlength())
if step == 0: # index only
- return space.wrap(ord(self.buf.getitem(start)))
+ a = start * self.itemsize
+ b = a + self.itemsize
+ return space.wrapbytes(
+ ''.join([self.buf.getitem(i) for i in range(a, b)]))
elif step == 1:
- buf = SubBuffer(self.buf, start, size)
- return W_MemoryView(buf)
+ buf = SubBuffer(self.buf, start * self.itemsize,
+ size * self.itemsize)
+ return W_MemoryView(buf, self.format, self.itemsize)
else:
raise oefmt(space.w_NotImplementedError, "")
def descr_setitem(self, space, w_index, w_obj):
self._check_released(space)
- _buffer_setitem(space, self.buf, w_index, w_obj, as_int=True)
+ if self.buf.readonly:
+ raise oefmt(space.w_TypeError, "cannot modify read-only memory")
+ start, stop, step, size = space.decode_index4(w_index, self.getlength())
+ if step not in (0, 1):
+ raise oefmt(space.w_NotImplementedError, "")
+ value = space.buffer_w(w_obj, space.BUF_CONTIG_RO)
+ if value.getlength() != size * self.itemsize:
+ raise oefmt(space.w_ValueError,
+ "cannot modify size of memoryview object")
+ self.buf.setslice(start * self.itemsize, value.as_str())
def descr_len(self, space):
self._check_released(space)
- return space.wrap(self.buf.getlength())
+ return space.wrap(self.getlength())
def w_get_format(self, space):
self._check_released(space)
- return space.wrap("B")
+ return space.wrap(self.format)
def w_get_itemsize(self, space):
self._check_released(space)
- return space.wrap(1)
+ return space.wrap(self.itemsize)
def w_get_ndim(self, space):
self._check_released(space)
@@ -142,7 +135,7 @@
def w_get_strides(self, space):
self._check_released(space)
- return space.newtuple([space.wrap(1)])
+ return space.newtuple([space.wrap(self.itemsize)])
def w_get_suboffsets(self, space):
self._check_released(space)
@@ -169,8 +162,8 @@
def _check_released(self, space):
if self.buf is None:
- raise OperationError(space.w_ValueError, space.wrap(
- "operation forbidden on released memoryview object"))
+ raise oefmt(space.w_ValueError,
+ "operation forbidden on released memoryview object")
def descr_enter(self, space):
self._check_released(space)
diff --git a/pypy/objspace/std/test/test_intobject.py b/pypy/objspace/std/test/test_intobject.py
--- a/pypy/objspace/std/test/test_intobject.py
+++ b/pypy/objspace/std/test/test_intobject.py
@@ -476,11 +476,20 @@
(10, 4),
(150, 8),
(-1, 1),
+ (-2, 2),
+ (-3, 2),
+ (-4, 3),
(-10, 4),
(-150, 8),
]:
assert val.bit_length() == bits
+ def test_bit_length_max(self):
+ import sys
+ val = -sys.maxsize-1
+ bits = 32 if val == -2147483648 else 64
+ assert val.bit_length() == bits
+
def test_int_real(self):
class A(int): pass
b = A(5).real
diff --git a/pypy/objspace/std/test/test_memoryobject.py b/pypy/objspace/std/test/test_memoryobject.py
--- a/pypy/objspace/std/test/test_memoryobject.py
+++ b/pypy/objspace/std/test/test_memoryobject.py
@@ -133,8 +133,31 @@
raises(ValueError, bytes, v)
assert "released memory" in repr(v)
+ def test_int_array_buffer(self):
+ import array
+ m = memoryview(array.array('i', list(range(10))))
+ assert m.format == 'i'
+ assert m.itemsize == 4
+ assert len(m) == 10
+ assert len(m.tobytes()) == 40
+ assert m[0] == b'\x00\x00\x00\x00'
+ m[0] = b'\x00\x00\x00\x01'
+ assert m[0] == b'\x00\x00\x00\x01'
+
+ def test_int_array_slice(self):
+ import array
+ m = memoryview(array.array('i', list(range(10))))
+ slice = m[2:8]
+ assert slice.format == 'i'
+ assert slice.itemsize == 4
+ assert len(slice) == 6
+ assert len(slice.tobytes()) == 24
+ assert slice[0] in (b'\x00\x00\x00\x02', b'\x02\x00\x00\x00')
+ slice[0] = b'\x00\x00\x00\x01'
+ assert slice[0] == b'\x00\x00\x00\x01'
+ assert m[2] == b'\x00\x00\x00\x01'
+
def test_pypy_raw_address_base(self):
raises(ValueError, memoryview(b"foobar")._pypy_raw_address)
e = raises(ValueError, memoryview(bytearray(b"foobar"))._pypy_raw_address)
assert 'BytearrayBuffer' in str(e.value)
-
diff --git a/rpython/flowspace/flowcontext.py b/rpython/flowspace/flowcontext.py
--- a/rpython/flowspace/flowcontext.py
+++ b/rpython/flowspace/flowcontext.py
@@ -12,8 +12,7 @@
from rpython.flowspace.argument import CallSpec
from rpython.flowspace.model import (Constant, Variable, Block, Link,
c_last_exception, const, FSException)
-from rpython.flowspace.framestate import (FrameState, recursively_unflatten,
- recursively_flatten)
+from rpython.flowspace.framestate import FrameState
from rpython.flowspace.specialcase import (rpython_print_item,
rpython_print_newline)
from rpython.flowspace.operation import op
@@ -278,6 +277,7 @@
"cmp_exc_match",
]
+
class FlowContext(object):
def __init__(self, graph, code):
self.graph = graph
@@ -307,112 +307,91 @@
The locals are ordered according to self.pycode.signature.
"""
- self.valuestackdepth = code.co_nlocals
- self.locals_stack_w = [None] * (code.co_stacksize + code.co_nlocals)
+ self.nlocals = code.co_nlocals
+ self.locals_w = [None] * code.co_nlocals
+ self.stack = []
+
+ @property
+ def stackdepth(self):
+ return len(self.stack)
def pushvalue(self, w_object):
- depth = self.valuestackdepth
- self.locals_stack_w[depth] = w_object
- self.valuestackdepth = depth + 1
+ self.stack.append(w_object)
def popvalue(self):
- depth = self.valuestackdepth - 1
- assert depth >= self.pycode.co_nlocals, "pop from empty value stack"
- w_object = self.locals_stack_w[depth]
- self.locals_stack_w[depth] = None
- self.valuestackdepth = depth
- return w_object
+ return self.stack.pop()
def peekvalue(self, index_from_top=0):
# NOTE: top of the stack is peekvalue(0).
- index = self.valuestackdepth + ~index_from_top
- assert index >= self.pycode.co_nlocals, (
- "peek past the bottom of the stack")
- return self.locals_stack_w[index]
+ index = ~index_from_top
+ return self.stack[index]
def settopvalue(self, w_object, index_from_top=0):
- index = self.valuestackdepth + ~index_from_top
- assert index >= self.pycode.co_nlocals, (
- "settop past the bottom of the stack")
- self.locals_stack_w[index] = w_object
+ index = ~index_from_top
+ self.stack[index] = w_object
def popvalues(self, n):
- values_w = [self.popvalue() for i in range(n)]
- values_w.reverse()
+ if n == 0:
+ return []
+ values_w = self.stack[-n:]
+ del self.stack[-n:]
return values_w
- def dropvalues(self, n):
- finaldepth = self.valuestackdepth - n
- for n in range(finaldepth, self.valuestackdepth):
- self.locals_stack_w[n] = None
- self.valuestackdepth = finaldepth
-
def dropvaluesuntil(self, finaldepth):
- for n in range(finaldepth, self.valuestackdepth):
- self.locals_stack_w[n] = None
- self.valuestackdepth = finaldepth
-
- def save_locals_stack(self):
- return self.locals_stack_w[:self.valuestackdepth]
-
- def restore_locals_stack(self, items_w):
- self.locals_stack_w[:len(items_w)] = items_w
- self.dropvaluesuntil(len(items_w))
+ del self.stack[finaldepth:]
def getstate(self, next_offset):
- # getfastscope() can return real None, for undefined locals
- data = self.save_locals_stack()
- if self.last_exception is None:
- data.append(Constant(None))
- data.append(Constant(None))
- else:
- data.append(self.last_exception.w_type)
- data.append(self.last_exception.w_value)
- recursively_flatten(data)
- return FrameState(data, self.blockstack[:], next_offset)
+ return FrameState(self.locals_w[:], self.stack[:],
+ self.last_exception, self.blockstack[:], next_offset)
def setstate(self, state):
""" Reset the context to the given frame state. """
- data = state.mergeable[:]
- recursively_unflatten(data)
- self.restore_locals_stack(data[:-2]) # Nones == undefined locals
- if data[-2] == Constant(None):
- assert data[-1] == Constant(None)
- self.last_exception = None
- else:
- self.last_exception = FSException(data[-2], data[-1])
+ self.locals_w = state.locals_w[:]
+ self.stack = state.stack[:]
+ self.last_exception = state.last_exception
self.blockstack = state.blocklist[:]
+ self._normalize_raise_signals()
+
+ def _normalize_raise_signals(self):
+ st = self.stack
+ for i in range(len(st)):
+ if isinstance(st[i], RaiseImplicit):
+ st[i] = Raise(st[i].w_exc)
def guessbool(self, w_condition):
if isinstance(w_condition, Constant):
return w_condition.value
return self.recorder.guessbool(self, w_condition)
- def record(self, spaceop):
+ def maybe_merge(self):
recorder = self.recorder
if getattr(recorder, 'final_state', None) is not None:
self.mergeblock(recorder.crnt_block, recorder.final_state)
raise StopFlowing
+
+ def record(self, spaceop):
spaceop.offset = self.last_offset
- recorder.append(spaceop)
+ self.recorder.append(spaceop)
def do_op(self, op):
+ self.maybe_merge()
self.record(op)
self.guessexception(op.canraise)
return op.result
- def guessexception(self, exceptions, force=False):
+ def guessexception(self, exceptions):
"""
Catch possible exceptions implicitly.
"""
if not exceptions:
return
- if not force and not any(isinstance(block, (ExceptBlock, FinallyBlock))
- for block in self.blockstack):
- # The implicit exception wouldn't be caught and would later get
- # removed, so don't bother creating it.
- return
- self.recorder.guessexception(self, *exceptions)
+ # Implicit exceptions are ignored unless they are caught explicitly
+ if self.has_exc_handler():
+ self.recorder.guessexception(self, *exceptions)
+
+ def has_exc_handler(self):
+ return any(isinstance(block, (ExceptBlock, FinallyBlock))
+ for block in self.blockstack)
def build_flow(self):
graph = self.graph
@@ -430,35 +409,8 @@
while True:
next_offset = self.handle_bytecode(next_offset)
self.recorder.final_state = self.getstate(next_offset)
-
- except RaiseImplicit as e:
- w_exc = e.w_exc
- if isinstance(w_exc.w_type, Constant):
- exc_cls = w_exc.w_type.value
- else:
- exc_cls = Exception
- msg = "implicit %s shouldn't occur" % exc_cls.__name__
- w_type = Constant(AssertionError)
- w_value = Constant(AssertionError(msg))
- link = Link([w_type, w_value], self.graph.exceptblock)
- self.recorder.crnt_block.closeblock(link)
-
- except Raise as e:
- w_exc = e.w_exc
- if w_exc.w_type == const(ImportError):
- msg = 'import statement always raises %s' % e
- raise ImportError(msg)
- link = Link([w_exc.w_type, w_exc.w_value], self.graph.exceptblock)
- self.recorder.crnt_block.closeblock(link)
-
except StopFlowing:
pass
-
- except Return as exc:
- w_result = exc.w_value
- link = Link([w_result], self.graph.returnblock)
- self.recorder.crnt_block.closeblock(link)
-
except FlowingError as exc:
if exc.ctx is None:
exc.ctx = self
@@ -476,14 +428,8 @@
if newstate is not None:
break
else:
- newstate = currentstate.copy()
- newblock = SpamBlock(newstate)
- # unconditionally link the current block to the newblock
- outputargs = currentstate.getoutputargs(newstate)
- link = Link(outputargs, newblock)
- currentblock.closeblock(link)
+ newblock = self.make_next_block(currentblock, currentstate)
candidates.insert(0, newblock)
- self.pendingblocks.append(newblock)
return
if newstate.matches(block.framestate):
@@ -493,7 +439,7 @@
newblock = SpamBlock(newstate)
varnames = self.pycode.co_varnames
- for name, w_value in zip(varnames, newstate.mergeable):
+ for name, w_value in zip(varnames, newstate.locals_w):
if isinstance(w_value, Variable):
w_value.rename(name)
# unconditionally link the current block to the newblock
@@ -513,11 +459,21 @@
candidates.insert(0, newblock)
self.pendingblocks.append(newblock)
+ def make_next_block(self, block, state):
+ newstate = state.copy()
+ newblock = SpamBlock(newstate)
+ # unconditionally link the current block to the newblock
+ outputargs = state.getoutputargs(newstate)
+ link = Link(outputargs, newblock)
+ block.closeblock(link)
+ self.pendingblocks.append(newblock)
+ return newblock
+
# hack for unrolling iterables, don't use this
def replace_in_stack(self, oldvalue, newvalue):
w_new = Constant(newvalue)
- stack_items_w = self.locals_stack_w
- for i in range(self.valuestackdepth - 1, self.pycode.co_nlocals - 1, -1):
+ stack_items_w = self.stack
+ for i in range(self.stackdepth - 1, - 1, -1):
w_v = stack_items_w[i]
if isinstance(w_v, Constant):
if w_v.value is oldvalue:
@@ -541,7 +497,7 @@
if isinstance(signal, block.handles):
return block.handle(self, signal)
block.cleanupstack(self)
- return signal.nomoreblocks()
+ return signal.nomoreblocks(self)
def getlocalvarname(self, index):
return self.pycode.co_varnames[index]
@@ -870,7 +826,7 @@
op.simple_call(w_exitfunc, w_None, w_None, w_None).eval(self)
def LOAD_FAST(self, varindex):
- w_value = self.locals_stack_w[varindex]
+ w_value = self.locals_w[varindex]
if w_value is None:
raise FlowingError("Local variable referenced before assignment")
self.pushvalue(w_value)
@@ -915,7 +871,7 @@
def STORE_FAST(self, varindex):
w_newvalue = self.popvalue()
assert w_newvalue is not None
- self.locals_stack_w[varindex] = w_newvalue
+ self.locals_w[varindex] = w_newvalue
if isinstance(w_newvalue, Variable):
w_newvalue.rename(self.getlocalvarname(varindex))
@@ -1128,11 +1084,11 @@
op.simple_call(w_append_meth, w_value).eval(self)
def DELETE_FAST(self, varindex):
- if self.locals_stack_w[varindex] is None:
+ if self.locals_w[varindex] is None:
varname = self.getlocalvarname(varindex)
message = "local variable '%s' referenced before assignment"
raise UnboundLocalError(message, varname)
- self.locals_stack_w[varindex] = None
+ self.locals_w[varindex] = None
def STORE_MAP(self, oparg):
w_key = self.popvalue()
@@ -1220,25 +1176,32 @@
WHY_CONTINUE, Continue
WHY_YIELD not needed
"""
- def nomoreblocks(self):
+ def nomoreblocks(self, ctx):
raise BytecodeCorruption("misplaced bytecode - should not return")
+ def __eq__(self, other):
+ return type(other) is type(self) and other.args == self.args
+
class Return(FlowSignal):
"""Signals a 'return' statement.
- Argument is the wrapped object to return."""
-
+ Argument is the wrapped object to return.
+ """
def __init__(self, w_value):
self.w_value = w_value
- def nomoreblocks(self):
- raise Return(self.w_value)
+ def nomoreblocks(self, ctx):
+ w_result = self.w_value
+ link = Link([w_result], ctx.graph.returnblock)
+ ctx.recorder.crnt_block.closeblock(link)
+ raise StopFlowing
- def state_unpack_variables(self):
+ @property
+ def args(self):
return [self.w_value]
@staticmethod
- def state_pack_variables(w_value):
+ def rebuild(w_value):
return Return(w_value)
class Raise(FlowSignal):
@@ -1248,28 +1211,48 @@
def __init__(self, w_exc):
self.w_exc = w_exc
- def nomoreblocks(self):
- raise self
+ def nomoreblocks(self, ctx):
+ w_exc = self.w_exc
+ if w_exc.w_type == const(ImportError):
+ msg = 'import statement always raises %s' % self
+ raise ImportError(msg)
+ link = Link([w_exc.w_type, w_exc.w_value], ctx.graph.exceptblock)
+ ctx.recorder.crnt_block.closeblock(link)
+ raise StopFlowing
- def state_unpack_variables(self):
+ @property
+ def args(self):
return [self.w_exc.w_type, self.w_exc.w_value]
- @staticmethod
- def state_pack_variables(w_type, w_value):
- return Raise(FSException(w_type, w_value))
+ @classmethod
+ def rebuild(cls, w_type, w_value):
+ return cls(FSException(w_type, w_value))
class RaiseImplicit(Raise):
"""Signals an exception raised implicitly"""
+ def nomoreblocks(self, ctx):
+ w_exc = self.w_exc
+ if isinstance(w_exc.w_type, Constant):
+ exc_cls = w_exc.w_type.value
+ else:
+ exc_cls = Exception
+ msg = "implicit %s shouldn't occur" % exc_cls.__name__
+ w_type = Constant(AssertionError)
+ w_value = Constant(AssertionError(msg))
+ link = Link([w_type, w_value], ctx.graph.exceptblock)
+ ctx.recorder.crnt_block.closeblock(link)
+ raise StopFlowing
class Break(FlowSignal):
"""Signals a 'break' statement."""
- def state_unpack_variables(self):
+ @property
+ def args(self):
return []
@staticmethod
- def state_pack_variables():
+ def rebuild():
return Break.singleton
Break.singleton = Break()
@@ -1281,11 +1264,12 @@
def __init__(self, jump_to):
self.jump_to = jump_to
- def state_unpack_variables(self):
+ @property
+ def args(self):
return [const(self.jump_to)]
@staticmethod
- def state_pack_variables(w_jump_to):
+ def rebuild(w_jump_to):
return Continue(w_jump_to.value)
@@ -1295,21 +1279,21 @@
def __init__(self, ctx, handlerposition):
self.handlerposition = handlerposition
- self.valuestackdepth = ctx.valuestackdepth
+ self.stackdepth = ctx.stackdepth
def __eq__(self, other):
return (self.__class__ is other.__class__ and
self.handlerposition == other.handlerposition and
- self.valuestackdepth == other.valuestackdepth)
+ self.stackdepth == other.stackdepth)
def __ne__(self, other):
return not (self == other)
def __hash__(self):
- return hash((self.handlerposition, self.valuestackdepth))
+ return hash((self.handlerposition, self.stackdepth))
def cleanupstack(self, ctx):
- ctx.dropvaluesuntil(self.valuestackdepth)
+ ctx.dropvaluesuntil(self.stackdepth)
def handle(self, ctx, unroller):
raise NotImplementedError
diff --git a/rpython/flowspace/framestate.py b/rpython/flowspace/framestate.py
--- a/rpython/flowspace/framestate.py
+++ b/rpython/flowspace/framestate.py
@@ -1,21 +1,50 @@
-from rpython.flowspace.model import Variable, Constant
+from rpython.flowspace.model import Variable, Constant, FSException
from rpython.rlib.unroll import SpecTag
+def _copy(v):
+ from rpython.flowspace.flowcontext import FlowSignal
+ if isinstance(v, Variable):
+ return Variable(v)
+ elif isinstance(v, FlowSignal):
+ vars = [_copy(var) for var in v.args]
+ return v.rebuild(*vars)
+ else:
+ return v
+
+def _union(seq1, seq2):
+ return [union(v1, v2) for v1, v2 in zip(seq1, seq2)]
+
class FrameState(object):
- def __init__(self, mergeable, blocklist, next_offset):
- self.mergeable = mergeable
+ def __init__(self, locals_w, stack, last_exception, blocklist, next_offset):
+ self.locals_w = locals_w
+ self.stack = stack
+ self.last_exception = last_exception
self.blocklist = blocklist
self.next_offset = next_offset
+ self._mergeable = None
+
+ @property
+ def mergeable(self):
+ if self._mergeable is not None:
+ return self._mergeable
+ self._mergeable = data = self.locals_w + self.stack
+ if self.last_exception is None:
+ data.append(Constant(None))
+ data.append(Constant(None))
+ else:
+ data.append(self.last_exception.w_type)
+ data.append(self.last_exception.w_value)
+ recursively_flatten(data)
+ return data
def copy(self):
"Make a copy of this state in which all Variables are fresh."
- newstate = []
- for w in self.mergeable:
- if isinstance(w, Variable):
- w = Variable(w)
- newstate.append(w)
- return FrameState(newstate, self.blocklist, self.next_offset)
+ exc = self.last_exception
+ if exc is not None:
+ exc = FSException(_copy(exc.w_type), _copy(exc.w_value))
+ return FrameState(map(_copy, self.locals_w), map(_copy, self.stack),
+ exc, self.blocklist, self.next_offset)
def getvariables(self):
return [w for w in self.mergeable if isinstance(w, Variable)]
@@ -33,18 +62,31 @@
return False
return True
+ def _exc_args(self):
+ if self.last_exception is None:
+ return [Constant(None), Constant(None)]
+ else:
+ return [self.last_exception.w_type,
+ self.last_exception.w_value]
+
def union(self, other):
"""Compute a state that is at least as general as both self and other.
A state 'a' is more general than a state 'b' if all Variables in 'b'
are also Variables in 'a', but 'a' may have more Variables.
"""
- newstate = []
try:
- for w1, w2 in zip(self.mergeable, other.mergeable):
- newstate.append(union(w1, w2))
+ locals = _union(self.locals_w, other.locals_w)
+ stack = _union(self.stack, other.stack)
+ if self.last_exception is None and other.last_exception is None:
+ exc = None
+ else:
+ args1 = self._exc_args()
+ args2 = other._exc_args()
+ exc = FSException(union(args1[0], args2[0]),
+ union(args1[1], args2[1]))
except UnionError:
return None
- return FrameState(newstate, self.blocklist, self.next_offset)
+ return FrameState(locals, stack, exc, self.blocklist, self.next_offset)
def getoutputargs(self, targetstate):
"Return the output arguments needed to link self to targetstate."
@@ -61,6 +103,7 @@
def union(w1, w2):
"Union of two variables or constants."
+ from rpython.flowspace.flowcontext import FlowSignal
if w1 == w2:
return w1
if w1 is None or w2 is None:
@@ -69,38 +112,21 @@
if isinstance(w1, Variable) or isinstance(w2, Variable):
return Variable() # new fresh Variable
if isinstance(w1, Constant) and isinstance(w2, Constant):
- # FlowSignal represent stack unrollers in the stack.
- # They should not be merged because they will be unwrapped.
- # This is needed for try:except: and try:finally:, though
- # it makes the control flow a bit larger by duplicating the
- # handlers.
- dont_merge_w1 = w1 in UNPICKLE_TAGS or isinstance(w1.value, SpecTag)
- dont_merge_w2 = w2 in UNPICKLE_TAGS or isinstance(w2.value, SpecTag)
- if dont_merge_w1 or dont_merge_w2:
+ if isinstance(w1.value, SpecTag) or isinstance(w2.value, SpecTag):
raise UnionError
else:
return Variable() # generalize different constants
+ if isinstance(w1, FlowSignal) and isinstance(w2, FlowSignal):
+ if type(w1) is not type(w2):
+ raise UnionError
+ vars = [union(v1, v2) for v1, v2 in zip(w1.args, w2.args)]
+ return w1.rebuild(*vars)
+ if isinstance(w1, FlowSignal) or isinstance(w2, FlowSignal):
+ raise UnionError
raise TypeError('union of %r and %r' % (w1.__class__.__name__,
w2.__class__.__name__))
-# ____________________________________________________________
-#
-# We have to flatten out the state of the frame into a list of
-# Variables and Constants. This is done above by collecting the
-# locals and the items on the value stack, but the latter may contain
-# FlowSignal. We have to handle these specially, because
-# some of them hide references to more Variables and Constants.
-# The trick is to flatten ("pickle") them into the list so that the
-# extra Variables show up directly in the list too.
-
-class PickleTag:
- pass
-
-PICKLE_TAGS = {}
-UNPICKLE_TAGS = {}
-
-
def recursively_flatten(lst):
from rpython.flowspace.flowcontext import FlowSignal
i = 0
@@ -109,22 +135,4 @@
if not isinstance(unroller, FlowSignal):
i += 1
else:
- vars = unroller.state_unpack_variables()
- key = unroller.__class__, len(vars)
- try:
- tag = PICKLE_TAGS[key]
- except KeyError:
- tag = PICKLE_TAGS[key] = Constant(PickleTag())
- UNPICKLE_TAGS[tag] = key
- lst[i:i + 1] = [tag] + vars
-
-
-def recursively_unflatten(lst):
- for i in xrange(len(lst) - 1, -1, -1):
- item = lst[i]
- if item in UNPICKLE_TAGS:
- unrollerclass, argcount = UNPICKLE_TAGS[item]
- arguments = lst[i + 1:i + 1 + argcount]
- del lst[i + 1:i + 1 + argcount]
- unroller = unrollerclass.state_pack_variables(*arguments)
- lst[i] = unroller
+ lst[i:i + 1] = unroller.args
diff --git a/rpython/flowspace/operation.py b/rpython/flowspace/operation.py
--- a/rpython/flowspace/operation.py
+++ b/rpython/flowspace/operation.py
@@ -517,7 +517,7 @@
ctx.replace_in_stack(it, next_unroller)
return const(v)
w_item = ctx.do_op(self)
- ctx.guessexception([StopIteration, RuntimeError], force=True)
+ ctx.recorder.guessexception(ctx, StopIteration, RuntimeError)
return w_item
class GetAttr(SingleDispatchMixin, HLOperation):
diff --git a/rpython/flowspace/pygraph.py b/rpython/flowspace/pygraph.py
--- a/rpython/flowspace/pygraph.py
+++ b/rpython/flowspace/pygraph.py
@@ -11,10 +11,10 @@
def __init__(self, func, code):
from rpython.flowspace.flowcontext import SpamBlock
- data = [None] * code.co_nlocals
+ locals = [None] * code.co_nlocals
for i in range(code.formalargcount):
- data[i] = Variable(code.co_varnames[i])
- state = FrameState(data + [Constant(None), Constant(None)], [], 0)
+ locals[i] = Variable(code.co_varnames[i])
+ state = FrameState(locals, [], None, [], 0)
initialblock = SpamBlock(state)
super(PyGraph, self).__init__(self._sanitize_funcname(func), initialblock)
self.func = func
diff --git a/rpython/flowspace/test/test_flowcontext.py b/rpython/flowspace/test/test_flowcontext.py
new file mode 100644
--- /dev/null
+++ b/rpython/flowspace/test/test_flowcontext.py
@@ -0,0 +1,15 @@
+""" Unit tests for flowcontext.py """
+import pytest
+from rpython.flowspace.model import Variable, FSException
+from rpython.flowspace.flowcontext import (
+ Return, Raise, RaiseImplicit, Continue, Break)
+
+ at pytest.mark.parametrize('signal', [
+ Return(Variable()),
+ Raise(FSException(Variable(), Variable())),
+ RaiseImplicit(FSException(Variable(), Variable())),
+ Break(),
+ Continue(42),
+])
+def test_signals(signal):
+ assert signal.rebuild(*signal.args) == signal
diff --git a/rpython/flowspace/test/test_framestate.py b/rpython/flowspace/test/test_framestate.py
--- a/rpython/flowspace/test/test_framestate.py
+++ b/rpython/flowspace/test/test_framestate.py
@@ -15,7 +15,7 @@
ctx = FlowContext(graph, code)
# hack the frame
ctx.setstate(graph.startblock.framestate)
- ctx.locals_stack_w[ctx.pycode.co_nlocals-1] = Constant(None)
+ ctx.locals_w[-1] = Constant(None)
return ctx
def func_simple(x):
@@ -31,7 +31,7 @@
def test_neq_hacked_framestate(self):
ctx = self.get_context(self.func_simple)
fs1 = ctx.getstate(0)
- ctx.locals_stack_w[ctx.pycode.co_nlocals-1] = Variable()
+ ctx.locals_w[-1] = Variable()
fs2 = ctx.getstate(0)
assert not fs1.matches(fs2)
@@ -44,7 +44,7 @@
def test_union_on_hacked_framestates(self):
ctx = self.get_context(self.func_simple)
fs1 = ctx.getstate(0)
- ctx.locals_stack_w[ctx.pycode.co_nlocals-1] = Variable()
+ ctx.locals_w[-1] = Variable()
fs2 = ctx.getstate(0)
assert fs1.union(fs2).matches(fs2) # fs2 is more general
assert fs2.union(fs1).matches(fs2) # fs2 is more general
@@ -52,7 +52,7 @@
def test_restore_frame(self):
ctx = self.get_context(self.func_simple)
fs1 = ctx.getstate(0)
- ctx.locals_stack_w[ctx.pycode.co_nlocals-1] = Variable()
+ ctx.locals_w[-1] = Variable()
ctx.setstate(fs1)
assert fs1.matches(ctx.getstate(0))
@@ -71,26 +71,25 @@
def test_getoutputargs(self):
ctx = self.get_context(self.func_simple)
fs1 = ctx.getstate(0)
- ctx.locals_stack_w[ctx.pycode.co_nlocals-1] = Variable()
+ ctx.locals_w[-1] = Variable()
fs2 = ctx.getstate(0)
outputargs = fs1.getoutputargs(fs2)
# 'x' -> 'x' is a Variable
# locals_w[n-1] -> locals_w[n-1] is Constant(None)
- assert outputargs == [ctx.locals_stack_w[0], Constant(None)]
+ assert outputargs == [ctx.locals_w[0], Constant(None)]
def test_union_different_constants(self):
ctx = self.get_context(self.func_simple)
fs1 = ctx.getstate(0)
- ctx.locals_stack_w[ctx.pycode.co_nlocals-1] = Constant(42)
+ ctx.locals_w[-1] = Constant(42)
fs2 = ctx.getstate(0)
fs3 = fs1.union(fs2)
ctx.setstate(fs3)
- assert isinstance(ctx.locals_stack_w[ctx.pycode.co_nlocals-1],
- Variable) # generalized
+ assert isinstance(ctx.locals_w[-1], Variable) # generalized
def test_union_spectag(self):
ctx = self.get_context(self.func_simple)
fs1 = ctx.getstate(0)
- ctx.locals_stack_w[ctx.pycode.co_nlocals-1] = Constant(SpecTag())
+ ctx.locals_w[-1] = Constant(SpecTag())
fs2 = ctx.getstate(0)
assert fs1.union(fs2) is None # UnionError
diff --git a/rpython/jit/backend/arm/arch.py b/rpython/jit/backend/arm/arch.py
--- a/rpython/jit/backend/arm/arch.py
+++ b/rpython/jit/backend/arm/arch.py
@@ -1,4 +1,3 @@
-FUNC_ALIGN = 8
WORD = 4
DOUBLE_WORD = 8
diff --git a/rpython/jit/backend/arm/assembler.py b/rpython/jit/backend/arm/assembler.py
--- a/rpython/jit/backend/arm/assembler.py
+++ b/rpython/jit/backend/arm/assembler.py
@@ -4,7 +4,7 @@
from rpython.jit.backend.arm import conditions as c, registers as r
from rpython.jit.backend.arm import shift
-from rpython.jit.backend.arm.arch import (WORD, DOUBLE_WORD, FUNC_ALIGN,
+from rpython.jit.backend.arm.arch import (WORD, DOUBLE_WORD,
JITFRAME_FIXED_SIZE)
from rpython.jit.backend.arm.codebuilder import InstrBuilder, OverwritingBuilder
from rpython.jit.backend.arm.locations import imm, StackLocation, get_fp_offset
@@ -484,10 +484,6 @@
self.mc.BL(target)
return startpos
- def align(self):
- while(self.mc.currpos() % FUNC_ALIGN != 0):
- self.mc.writechar(chr(0))
-
def gen_func_epilog(self, mc=None, cond=c.AL):
gcrootmap = self.cpu.gc_ll_descr.gcrootmap
if mc is None:
@@ -557,7 +553,7 @@
debug_stop('jit-backend-ops')
def _call_header(self):
- self.align()
+ assert self.currpos() == 0
self.gen_func_prolog()
def _call_header_with_stack_check(self):
diff --git a/rpython/jit/backend/arm/callbuilder.py b/rpython/jit/backend/arm/callbuilder.py
--- a/rpython/jit/backend/arm/callbuilder.py
+++ b/rpython/jit/backend/arm/callbuilder.py
@@ -176,11 +176,14 @@
def write_real_errno(self, save_err):
if save_err & rffi.RFFI_READSAVED_ERRNO:
- # Just before a call, read 'rpy_errno' and write it into the
+ # Just before a call, read '*_errno' and write it into the
# real 'errno'. The r0-r3 registers contain arguments to the
# future call; the r5-r7 registers contain various stuff.
# We still have r8-r12.
- rpy_errno = llerrno.get_rpy_errno_offset(self.asm.cpu)
+ if save_err & rffi.RFFI_ALT_ERRNO:
+ rpy_errno = llerrno.get_alt_errno_offset(self.asm.cpu)
+ else:
+ rpy_errno = llerrno.get_rpy_errno_offset(self.asm.cpu)
p_errno = llerrno.get_p_errno_offset(self.asm.cpu)
self.mc.LDR_ri(r.r9.value, r.sp.value,
self.asm.saved_threadlocal_addr + self.current_sp)
@@ -199,10 +202,13 @@
def read_real_errno(self, save_err):
if save_err & rffi.RFFI_SAVE_ERRNO:
# Just after a call, read the real 'errno' and save a copy of
- # it inside our thread-local 'rpy_errno'. Registers r8-r12
+ # it inside our thread-local '*_errno'. Registers r8-r12
# are unused here, and registers r2-r3 never contain anything
# after the call.
- rpy_errno = llerrno.get_rpy_errno_offset(self.asm.cpu)
+ if save_err & rffi.RFFI_ALT_ERRNO:
+ rpy_errno = llerrno.get_alt_errno_offset(self.asm.cpu)
+ else:
+ rpy_errno = llerrno.get_rpy_errno_offset(self.asm.cpu)
p_errno = llerrno.get_p_errno_offset(self.asm.cpu)
self.mc.LDR_ri(r.r3.value, r.sp.value,
self.asm.saved_threadlocal_addr)
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,7 +1,7 @@
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, FUNC_ALIGN, PC_OFFSET)
+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
from rpython.rlib.objectmodel import we_are_translated
@@ -29,14 +29,9 @@
class AbstractARMBuilder(object):
-
def __init__(self, arch_version=7):
self.arch_version = arch_version
- def align(self):
- while(self.currpos() % FUNC_ALIGN != 0):
- self.writechar(chr(0))
-
def NOP(self):
self.MOV_rr(0, 0)
@@ -467,21 +462,6 @@
f.write(data[i])
f.close()
- # XXX remove and setup aligning in llsupport
- def materialize(self, asmmemmgr, allblocks, gcrootmap=None):
- size = self.get_relative_pos() + WORD
- malloced = asmmemmgr.malloc(size, size + 7)
- allblocks.append(malloced)
- rawstart = malloced[0]
- while(rawstart % FUNC_ALIGN != 0):
- rawstart += 1
- self.copy_to_raw_memory(rawstart)
- if self.gcroot_markers is not None:
- assert gcrootmap is not None
- for pos, mark in self.gcroot_markers:
- gcrootmap.put(rawstart + pos, mark)
- return rawstart
-
def clear_cache(self, addr):
if we_are_translated():
startaddr = rffi.cast(llmemory.Address, addr)
diff --git a/rpython/jit/backend/llsupport/asmmemmgr.py b/rpython/jit/backend/llsupport/asmmemmgr.py
--- a/rpython/jit/backend/llsupport/asmmemmgr.py
+++ b/rpython/jit/backend/llsupport/asmmemmgr.py
@@ -208,6 +208,8 @@
('data', lltype.FixedSizeArray(lltype.Char, SUBBLOCK_SIZE)))
SUBBLOCK_PTR.TO.become(SUBBLOCK)
+ ALIGN_MATERIALIZE = 16
+
gcroot_markers = None
def __init__(self, translated=None):
@@ -303,9 +305,12 @@
def materialize(self, asmmemmgr, allblocks, gcrootmap=None):
size = self.get_relative_pos()
+ align = self.ALIGN_MATERIALIZE
+ size += align - 1
malloced = asmmemmgr.malloc(size, size)
allblocks.append(malloced)
rawstart = malloced[0]
+ rawstart = (rawstart + align - 1) & (-align)
self.copy_to_raw_memory(rawstart)
if self.gcroot_markers is not None:
assert gcrootmap is not None
diff --git a/rpython/jit/backend/llsupport/llerrno.py b/rpython/jit/backend/llsupport/llerrno.py
--- a/rpython/jit/backend/llsupport/llerrno.py
+++ b/rpython/jit/backend/llsupport/llerrno.py
@@ -18,19 +18,41 @@
return 3 * WORD
+def get_debug_saved_alterrno(cpu):
+ return cpu._debug_errno_container[4]
+
+def set_debug_saved_alterrno(cpu, nerrno):
+ assert nerrno >= 0
+ cpu._debug_errno_container[4] = nerrno
+
+def get_alt_errno_offset(cpu):
+ if cpu.translate_support_code:
+ from rpython.rlib import rthread
+ return rthread.tlfield_alt_errno.getoffset()
+ else:
+ return 4 * WORD
+
+
def get_debug_saved_lasterror(cpu):
- return cpu._debug_errno_container[4]
+ return cpu._debug_errno_container[5]
def set_debug_saved_lasterror(cpu, nerrno):
assert nerrno >= 0
- cpu._debug_errno_container[4] = nerrno
+ cpu._debug_errno_container[5] = nerrno
def get_rpy_lasterror_offset(cpu):
if cpu.translate_support_code:
from rpython.rlib import rthread
return rthread.tlfield_rpy_lasterror.getoffset()
else:
- return 4 * WORD
+ return 5 * WORD
+
+def get_alt_lasterror_offset(cpu):
+ if cpu.translate_support_code:
+ from rpython.rlib import rthread
+ return rthread.tlfield_alt_lasterror.getoffset()
+ else:
+ return 6 * WORD
def _fetch_addr_errno():
diff --git a/rpython/jit/backend/llsupport/llmodel.py b/rpython/jit/backend/llsupport/llmodel.py
--- a/rpython/jit/backend/llsupport/llmodel.py
+++ b/rpython/jit/backend/llsupport/llmodel.py
@@ -63,7 +63,7 @@
ad.lendescr, FLAG_FLOAT)
More information about the pypy-commit
mailing list