Author: mattip <matti.pi...@gmail.com> Branch: stdlib-2.7.11 Changeset: r83597:72454c4374d2 Date: 2016-04-10 21:14 +0300 http://bitbucket.org/pypy/pypy/changeset/72454c4374d2/
Log: merge default into branch diff too long, truncating to 2000 out of 13183 lines diff --git a/.hgtags b/.hgtags --- a/.hgtags +++ b/.hgtags @@ -19,3 +19,4 @@ 850edf14b2c75573720f59e95767335fb1affe55 release-4.0.0 5f8302b8bf9f53056e40426f10c72151564e5b19 release-4.0.1 246c9cf22037b11dc0e8c29ce3f291d3b8c5935a release-5.0 +bbd45126bc691f669c4ebdfbd74456cd274c6b92 release-5.0.1 diff --git a/lib_pypy/_ctypes/structure.py b/lib_pypy/_ctypes/structure.py --- a/lib_pypy/_ctypes/structure.py +++ b/lib_pypy/_ctypes/structure.py @@ -67,7 +67,8 @@ subvalue = subfield.ctype fields[subname] = Field(subname, relpos, subvalue._sizeofinstances(), - subvalue, i, is_bitfield) + subvalue, i, is_bitfield, + inside_anon_field=fields[name]) else: resnames.append(name) names = resnames @@ -77,13 +78,15 @@ class Field(object): - def __init__(self, name, offset, size, ctype, num, is_bitfield): + def __init__(self, name, offset, size, ctype, num, is_bitfield, + inside_anon_field=None): self.__dict__['name'] = name self.__dict__['offset'] = offset self.__dict__['size'] = size self.__dict__['ctype'] = ctype self.__dict__['num'] = num self.__dict__['is_bitfield'] = is_bitfield + self.__dict__['inside_anon_field'] = inside_anon_field def __setattr__(self, name, value): raise AttributeError(name) @@ -95,6 +98,8 @@ def __get__(self, obj, cls=None): if obj is None: return self + if self.inside_anon_field is not None: + return getattr(self.inside_anon_field.__get__(obj), self.name) if self.is_bitfield: # bitfield member, use direct access return obj._buffer.__getattr__(self.name) @@ -105,6 +110,9 @@ return fieldtype._CData_output(suba, obj, offset) def __set__(self, obj, value): + if self.inside_anon_field is not None: + setattr(self.inside_anon_field.__get__(obj), self.name, value) + return fieldtype = self.ctype cobj = fieldtype.from_param(value) key = keepalive_key(self.num) diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py --- a/pypy/config/pypyoption.py +++ b/pypy/config/pypyoption.py @@ -46,7 +46,6 @@ except detect_cpu.ProcessorAutodetectError: pass - translation_modules = default_modules.copy() translation_modules.update([ "fcntl", "time", "select", "signal", "_rawffi", "zlib", "struct", "_md5", diff --git a/pypy/doc/__pypy__-module.rst b/pypy/doc/__pypy__-module.rst --- a/pypy/doc/__pypy__-module.rst +++ b/pypy/doc/__pypy__-module.rst @@ -18,6 +18,7 @@ - ``bytebuffer(length)``: return a new read-write buffer of the given length. It works like a simplified array of characters (actually, depending on the configuration the ``array`` module internally uses this). + - ``attach_gdb()``: start a GDB at the interpreter-level (or a PDB before translation). Transparent Proxy Functionality @@ -37,4 +38,3 @@ -------------------------------------------------------- - ``isfake(obj)``: returns True if ``obj`` is faked. - - ``interp_pdb()``: start a pdb at interpreter-level. 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 @@ -23,3 +23,32 @@ Implement yet another strange numpy indexing compatibility; indexing by a scalar returns a scalar + +.. branch: fix_transpose_for_list_v3 + +Allow arguments to transpose to be sequences + +.. branch: jit-leaner-frontend + +Improve the tracing speed in the frontend as well as heapcache by using a more compact representation +of traces + +.. branch: win32-lib-name + +.. branch: remove-frame-forcing-in-executioncontext + +.. branch: rposix-for-3 + +Wrap more POSIX functions in `rpython.rlib.rposix`. + +.. branch: cleanup-history-rewriting + +A local clean-up in the JIT front-end. + +.. branch: jit-constptr-2 + +Remove the forced minor collection that occurs when rewriting the +assembler at the start of the JIT backend. This is done by emitting +the ConstPtrs in a separate table, and loading from the table. It +gives improved warm-up time and memory usage, and also removes +annoying special-purpose code for pinned pointers. diff --git a/pypy/goal/targetpypystandalone.py b/pypy/goal/targetpypystandalone.py --- a/pypy/goal/targetpypystandalone.py +++ b/pypy/goal/targetpypystandalone.py @@ -240,8 +240,9 @@ "when --shared is on (it is by default). " "See issue #1971.") if sys.platform == 'win32': - config.translation.libname = '..\\..\\libs\\python27.lib' - thisdir.join('..', '..', 'libs').ensure(dir=1) + libdir = thisdir.join('..', '..', 'libs') + libdir.ensure(dir=1) + config.translation.libname = str(libdir.join('python27.lib')) if config.translation.thread: config.objspace.usemodules.thread = True diff --git a/pypy/interpreter/error.py b/pypy/interpreter/error.py --- a/pypy/interpreter/error.py +++ b/pypy/interpreter/error.py @@ -291,13 +291,7 @@ return tb def set_traceback(self, traceback): - """Set the current traceback. It should either be a traceback - pointing to some already-escaped frame, or a traceback for the - current frame. To support the latter case we do not mark the - frame as escaped. The idea is that it will be marked as escaping - only if the exception really propagates out of this frame, by - executioncontext.leave() being called with got_exception=True. - """ + """Set the current traceback.""" self._application_traceback = traceback diff --git a/pypy/module/__pypy__/__init__.py b/pypy/module/__pypy__/__init__.py --- a/pypy/module/__pypy__/__init__.py +++ b/pypy/module/__pypy__/__init__.py @@ -90,6 +90,7 @@ 'save_module_content_for_future_reload': 'interp_magic.save_module_content_for_future_reload', 'decode_long' : 'interp_magic.decode_long', + '_promote' : 'interp_magic._promote', } if sys.platform == 'win32': interpleveldefs['get_console_cp'] = 'interp_magic.get_console_cp' diff --git a/pypy/module/__pypy__/interp_magic.py b/pypy/module/__pypy__/interp_magic.py --- a/pypy/module/__pypy__/interp_magic.py +++ b/pypy/module/__pypy__/interp_magic.py @@ -168,3 +168,23 @@ except InvalidEndiannessError: raise oefmt(space.w_ValueError, "invalid byteorder argument") return space.newlong_from_rbigint(result) + +def _promote(space, w_obj): + """ Promote the first argument of the function and return it. Promote is by + value for ints, floats, strs, unicodes (but not subclasses thereof) and by + reference otherwise. (Unicodes not supported right now.) + + This function is experimental!""" + from rpython.rlib import jit + if space.is_w(space.type(w_obj), space.w_int): + jit.promote(space.int_w(w_obj)) + elif space.is_w(space.type(w_obj), space.w_float): + jit.promote(space.float_w(w_obj)) + elif space.is_w(space.type(w_obj), space.w_str): + jit.promote_string(space.str_w(w_obj)) + elif space.is_w(space.type(w_obj), space.w_unicode): + raise OperationError(space.w_TypeError, space.wrap( + "promoting unicode unsupported")) + else: + jit.promote(w_obj) + return w_obj diff --git a/pypy/module/__pypy__/test/test_magic.py b/pypy/module/__pypy__/test/test_magic.py --- a/pypy/module/__pypy__/test/test_magic.py +++ b/pypy/module/__pypy__/test/test_magic.py @@ -47,3 +47,16 @@ assert decode_long('\x00\x80', 'little', False) == 32768 assert decode_long('\x00\x80', 'little', True) == -32768 raises(ValueError, decode_long, '', 'foo') + + def test_promote(self): + from __pypy__ import _promote + assert _promote(1) == 1 + assert _promote(1.1) == 1.1 + assert _promote("abc") == "abc" + raises(TypeError, _promote, u"abc") + l = [] + assert _promote(l) is l + class A(object): + pass + a = A() + assert _promote(a) is a diff --git a/pypy/module/_cffi_backend/ctypeptr.py b/pypy/module/_cffi_backend/ctypeptr.py --- a/pypy/module/_cffi_backend/ctypeptr.py +++ b/pypy/module/_cffi_backend/ctypeptr.py @@ -124,7 +124,7 @@ s = rffi.charp2str(ptr) else: s = rffi.charp2strn(ptr, length) - return space.wrap(s) + return space.wrapbytes(s) # # pointer to a wchar_t: builds and returns a unicode if self.is_unichar_ptr_or_array(): @@ -372,15 +372,15 @@ rffi_fclose(self.llf) -def prepare_file_argument(space, fileobj): - fileobj.direct_flush() - if fileobj.cffi_fileobj is None: - fd = fileobj.direct_fileno() +def prepare_file_argument(space, w_fileobj): + w_fileobj.direct_flush() + if w_fileobj.cffi_fileobj is None: + fd = w_fileobj.direct_fileno() if fd < 0: raise OperationError(space.w_ValueError, space.wrap("file has no OS file descriptor")) try: - fileobj.cffi_fileobj = CffiFileObj(fd, fileobj.mode) + w_fileobj.cffi_fileobj = CffiFileObj(fd, w_fileobj.mode) except OSError, e: raise wrap_oserror(space, e) - return rffi.cast(rffi.CCHARP, fileobj.cffi_fileobj.llf) + return rffi.cast(rffi.CCHARP, w_fileobj.cffi_fileobj.llf) diff --git a/pypy/module/_file/test/test_file.py b/pypy/module/_file/test/test_file.py --- a/pypy/module/_file/test/test_file.py +++ b/pypy/module/_file/test/test_file.py @@ -285,6 +285,8 @@ from posix import openpty, fdopen, write, close except ImportError: skip('no openpty on this platform') + if 'gnukfreebsd' in sys.platform: + skip('close() hangs forever on kFreeBSD') read_fd, write_fd = openpty() write(write_fd, 'Abc\n') close(write_fd) diff --git a/pypy/module/_multibytecodec/src/cjkcodecs/cjkcodecs.h b/pypy/module/_multibytecodec/src/cjkcodecs/cjkcodecs.h --- a/pypy/module/_multibytecodec/src/cjkcodecs/cjkcodecs.h +++ b/pypy/module/_multibytecodec/src/cjkcodecs/cjkcodecs.h @@ -10,6 +10,7 @@ #define _CJKCODECS_H_ #include "src/cjkcodecs/multibytecodec.h" +#include "src/cjkcodecs/fixnames.h" /* a unicode "undefined" codepoint */ diff --git a/pypy/module/_multibytecodec/src/cjkcodecs/fixnames.h b/pypy/module/_multibytecodec/src/cjkcodecs/fixnames.h new file mode 100644 --- /dev/null +++ b/pypy/module/_multibytecodec/src/cjkcodecs/fixnames.h @@ -0,0 +1,9 @@ + +/* this is only included from the .c files in this directory: rename + these pypymbc-prefixed names to locally define the CPython names */ +typedef pypymbc_ssize_t Py_ssize_t; +#define PY_SSIZE_T_MAX ((Py_ssize_t)(((size_t) -1) >> 1)) +#define Py_UNICODE_SIZE pypymbc_UNICODE_SIZE +typedef pypymbc_wchar_t Py_UNICODE; +typedef pypymbc_ucs4_t ucs4_t; +typedef pypymbc_ucs2_t ucs2_t, DBCHAR; diff --git a/pypy/module/_multibytecodec/src/cjkcodecs/multibytecodec.c b/pypy/module/_multibytecodec/src/cjkcodecs/multibytecodec.c --- a/pypy/module/_multibytecodec/src/cjkcodecs/multibytecodec.c +++ b/pypy/module/_multibytecodec/src/cjkcodecs/multibytecodec.c @@ -1,6 +1,7 @@ #include <stdlib.h> #include <string.h> #include "src/cjkcodecs/multibytecodec.h" +#include "src/cjkcodecs/fixnames.h" struct pypy_cjk_dec_s *pypy_cjk_dec_new(const MultibyteCodec *codec) diff --git a/pypy/module/_multibytecodec/src/cjkcodecs/multibytecodec.h b/pypy/module/_multibytecodec/src/cjkcodecs/multibytecodec.h --- a/pypy/module/_multibytecodec/src/cjkcodecs/multibytecodec.h +++ b/pypy/module/_multibytecodec/src/cjkcodecs/multibytecodec.h @@ -9,31 +9,28 @@ #include <assert.h> #ifdef _WIN64 -typedef __int64 ssize_t +typedef __int64 pypymbc_ssize_t #elif defined(_WIN32) -typedef int ssize_t; +typedef int pypymbc_ssize_t; #else #include <unistd.h> -#endif - -#ifndef Py_UNICODE_SIZE -#ifdef _WIN32 -#define Py_UNICODE_SIZE 2 -#else -#define Py_UNICODE_SIZE 4 -#endif -typedef wchar_t Py_UNICODE; -typedef ssize_t Py_ssize_t; -#define PY_SSIZE_T_MAX ((Py_ssize_t)(((size_t) -1) >> 1)) +typedef ssize_t pypymbc_ssize_t; #endif #ifdef _WIN32 -typedef unsigned int ucs4_t; -typedef unsigned short ucs2_t, DBCHAR; +#define pypymbc_UNICODE_SIZE 2 +#else +#define pypymbc_UNICODE_SIZE 4 +#endif +typedef wchar_t pypymbc_wchar_t; + +#ifdef _WIN32 +typedef unsigned int pypymbc_ucs4_t; +typedef unsigned short pypymbc_ucs2_t; #else #include <stdint.h> -typedef uint32_t ucs4_t; -typedef uint16_t ucs2_t, DBCHAR; +typedef uint32_t pypymbc_ucs4_t; +typedef uint16_t pypymbc_ucs2_t; #endif @@ -42,28 +39,28 @@ void *p; int i; unsigned char c[8]; - ucs2_t u2[4]; - ucs4_t u4[2]; + pypymbc_ucs2_t u2[4]; + pypymbc_ucs4_t u4[2]; } MultibyteCodec_State; typedef int (*mbcodec_init)(const void *config); -typedef Py_ssize_t (*mbencode_func)(MultibyteCodec_State *state, +typedef pypymbc_ssize_t (*mbencode_func)(MultibyteCodec_State *state, const void *config, - const Py_UNICODE **inbuf, Py_ssize_t inleft, - unsigned char **outbuf, Py_ssize_t outleft, + const pypymbc_wchar_t **inbuf, pypymbc_ssize_t inleft, + unsigned char **outbuf, pypymbc_ssize_t outleft, int flags); typedef int (*mbencodeinit_func)(MultibyteCodec_State *state, const void *config); -typedef Py_ssize_t (*mbencodereset_func)(MultibyteCodec_State *state, +typedef pypymbc_ssize_t (*mbencodereset_func)(MultibyteCodec_State *state, const void *config, - unsigned char **outbuf, Py_ssize_t outleft); -typedef Py_ssize_t (*mbdecode_func)(MultibyteCodec_State *state, + unsigned char **outbuf, pypymbc_ssize_t outleft); +typedef pypymbc_ssize_t (*mbdecode_func)(MultibyteCodec_State *state, const void *config, - const unsigned char **inbuf, Py_ssize_t inleft, - Py_UNICODE **outbuf, Py_ssize_t outleft); + const unsigned char **inbuf, pypymbc_ssize_t inleft, + pypymbc_wchar_t **outbuf, pypymbc_ssize_t outleft); typedef int (*mbdecodeinit_func)(MultibyteCodec_State *state, const void *config); -typedef Py_ssize_t (*mbdecodereset_func)(MultibyteCodec_State *state, +typedef pypymbc_ssize_t (*mbdecodereset_func)(MultibyteCodec_State *state, const void *config); typedef struct MultibyteCodec_s { @@ -94,59 +91,59 @@ const MultibyteCodec *codec; MultibyteCodec_State state; const unsigned char *inbuf_start, *inbuf, *inbuf_end; - Py_UNICODE *outbuf_start, *outbuf, *outbuf_end; + pypymbc_wchar_t *outbuf_start, *outbuf, *outbuf_end; }; RPY_EXTERN struct pypy_cjk_dec_s *pypy_cjk_dec_new(const MultibyteCodec *codec); RPY_EXTERN -Py_ssize_t pypy_cjk_dec_init(struct pypy_cjk_dec_s *d, - char *inbuf, Py_ssize_t inlen); +pypymbc_ssize_t pypy_cjk_dec_init(struct pypy_cjk_dec_s *d, + char *inbuf, pypymbc_ssize_t inlen); RPY_EXTERN void pypy_cjk_dec_free(struct pypy_cjk_dec_s *); RPY_EXTERN -Py_ssize_t pypy_cjk_dec_chunk(struct pypy_cjk_dec_s *); +pypymbc_ssize_t pypy_cjk_dec_chunk(struct pypy_cjk_dec_s *); RPY_EXTERN -Py_UNICODE *pypy_cjk_dec_outbuf(struct pypy_cjk_dec_s *); +pypymbc_wchar_t *pypy_cjk_dec_outbuf(struct pypy_cjk_dec_s *); RPY_EXTERN -Py_ssize_t pypy_cjk_dec_outlen(struct pypy_cjk_dec_s *); +pypymbc_ssize_t pypy_cjk_dec_outlen(struct pypy_cjk_dec_s *); RPY_EXTERN -Py_ssize_t pypy_cjk_dec_inbuf_remaining(struct pypy_cjk_dec_s *d); +pypymbc_ssize_t pypy_cjk_dec_inbuf_remaining(struct pypy_cjk_dec_s *d); RPY_EXTERN -Py_ssize_t pypy_cjk_dec_inbuf_consumed(struct pypy_cjk_dec_s* d); +pypymbc_ssize_t pypy_cjk_dec_inbuf_consumed(struct pypy_cjk_dec_s* d); RPY_EXTERN -Py_ssize_t pypy_cjk_dec_replace_on_error(struct pypy_cjk_dec_s* d, - Py_UNICODE *, Py_ssize_t, Py_ssize_t); +pypymbc_ssize_t pypy_cjk_dec_replace_on_error(struct pypy_cjk_dec_s* d, + pypymbc_wchar_t *, pypymbc_ssize_t, pypymbc_ssize_t); struct pypy_cjk_enc_s { const MultibyteCodec *codec; MultibyteCodec_State state; - const Py_UNICODE *inbuf_start, *inbuf, *inbuf_end; + const pypymbc_wchar_t *inbuf_start, *inbuf, *inbuf_end; unsigned char *outbuf_start, *outbuf, *outbuf_end; }; RPY_EXTERN struct pypy_cjk_enc_s *pypy_cjk_enc_new(const MultibyteCodec *codec); RPY_EXTERN -Py_ssize_t pypy_cjk_enc_init(struct pypy_cjk_enc_s *d, - Py_UNICODE *inbuf, Py_ssize_t inlen); +pypymbc_ssize_t pypy_cjk_enc_init(struct pypy_cjk_enc_s *d, + pypymbc_wchar_t *inbuf, pypymbc_ssize_t inlen); RPY_EXTERN void pypy_cjk_enc_free(struct pypy_cjk_enc_s *); RPY_EXTERN -Py_ssize_t pypy_cjk_enc_chunk(struct pypy_cjk_enc_s *, Py_ssize_t); +pypymbc_ssize_t pypy_cjk_enc_chunk(struct pypy_cjk_enc_s *, pypymbc_ssize_t); RPY_EXTERN -Py_ssize_t pypy_cjk_enc_reset(struct pypy_cjk_enc_s *); +pypymbc_ssize_t pypy_cjk_enc_reset(struct pypy_cjk_enc_s *); RPY_EXTERN char *pypy_cjk_enc_outbuf(struct pypy_cjk_enc_s *); RPY_EXTERN -Py_ssize_t pypy_cjk_enc_outlen(struct pypy_cjk_enc_s *); +pypymbc_ssize_t pypy_cjk_enc_outlen(struct pypy_cjk_enc_s *); RPY_EXTERN -Py_ssize_t pypy_cjk_enc_inbuf_remaining(struct pypy_cjk_enc_s *d); +pypymbc_ssize_t pypy_cjk_enc_inbuf_remaining(struct pypy_cjk_enc_s *d); RPY_EXTERN -Py_ssize_t pypy_cjk_enc_inbuf_consumed(struct pypy_cjk_enc_s* d); +pypymbc_ssize_t pypy_cjk_enc_inbuf_consumed(struct pypy_cjk_enc_s* d); RPY_EXTERN -Py_ssize_t pypy_cjk_enc_replace_on_error(struct pypy_cjk_enc_s* d, - char *, Py_ssize_t, Py_ssize_t); +pypymbc_ssize_t pypy_cjk_enc_replace_on_error(struct pypy_cjk_enc_s* d, + char *, pypymbc_ssize_t, pypymbc_ssize_t); RPY_EXTERN const MultibyteCodec *pypy_cjk_enc_getcodec(struct pypy_cjk_enc_s *); @@ -191,5 +188,7 @@ DEFINE_CODEC(big5) DEFINE_CODEC(cp950) +#undef DEFINE_CODEC + #endif diff --git a/pypy/module/_vmprof/test/test__vmprof.py b/pypy/module/_vmprof/test/test__vmprof.py --- a/pypy/module/_vmprof/test/test__vmprof.py +++ b/pypy/module/_vmprof/test/test__vmprof.py @@ -14,7 +14,7 @@ tmpfile2 = open(self.tmpfilename2, 'wb') tmpfileno2 = tmpfile2.fileno() - import struct, sys + import struct, sys, gc WORD = struct.calcsize('l') @@ -46,6 +46,8 @@ return count import _vmprof + gc.collect() # try to make the weakref list deterministic + gc.collect() # by freeing all dead code objects _vmprof.enable(tmpfileno, 0.01) _vmprof.disable() s = open(self.tmpfilename, 'rb').read() @@ -57,6 +59,8 @@ pass """ in d + gc.collect() + gc.collect() _vmprof.enable(tmpfileno2, 0.01) exec """def foo2(): 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 @@ -1,4 +1,4 @@ -from pypy.interpreter.error import OperationError +from pypy.interpreter.error import OperationError, oefmt from rpython.rtyper.lltypesystem import rffi, lltype from pypy.module.cpyext.api import ( cpython_api, cpython_struct, bootstrap_function, build_type_checkers, @@ -134,8 +134,14 @@ if from_ref(space, rffi.cast(PyObject, ref.c_ob_type)) is space.w_str: pass # typecheck returned "ok" without forcing 'ref' at all elif not PyString_Check(space, ref): # otherwise, use the alternate way - raise OperationError(space.w_TypeError, space.wrap( - "PyString_AsString only support strings")) + from pypy.module.cpyext.unicodeobject import ( + PyUnicode_Check, _PyUnicode_AsDefaultEncodedString) + if PyUnicode_Check(space, ref): + ref = _PyUnicode_AsDefaultEncodedString(space, ref, lltype.nullptr(rffi.CCHARP.TO)) + else: + raise oefmt(space.w_TypeError, + "expected string or Unicode object, %T found", + from_ref(space, ref)) ref_str = rffi.cast(PyStringObject, ref) if not ref_str.c_buffer: # copy string buffer @@ -147,8 +153,14 @@ @cpython_api([PyObject, rffi.CCHARPP, rffi.CArrayPtr(Py_ssize_t)], rffi.INT_real, error=-1) def PyString_AsStringAndSize(space, ref, buffer, length): if not PyString_Check(space, ref): - raise OperationError(space.w_TypeError, space.wrap( - "PyString_AsStringAndSize only support strings")) + from pypy.module.cpyext.unicodeobject import ( + PyUnicode_Check, _PyUnicode_AsDefaultEncodedString) + if PyUnicode_Check(space, ref): + ref = _PyUnicode_AsDefaultEncodedString(space, ref, lltype.nullptr(rffi.CCHARP.TO)) + else: + raise oefmt(space.w_TypeError, + "expected string or Unicode object, %T found", + from_ref(space, ref)) ref_str = rffi.cast(PyStringObject, ref) if not ref_str.c_buffer: # copy string buffer diff --git a/pypy/module/cpyext/include/unicodeobject.h b/pypy/module/cpyext/include/unicodeobject.h --- a/pypy/module/cpyext/include/unicodeobject.h +++ b/pypy/module/cpyext/include/unicodeobject.h @@ -20,8 +20,12 @@ typedef struct { PyObject_HEAD - Py_UNICODE *buffer; + Py_UNICODE *str; Py_ssize_t size; + long hash; /* Hash value; -1 if not set */ + PyObject *defenc; /* (Default) Encoded version as Python + string, or NULL; this is used for + implementing the buffer protocol */ } PyUnicodeObject; diff --git a/pypy/module/cpyext/test/test_bytesobject.py b/pypy/module/cpyext/test/test_bytesobject.py --- a/pypy/module/cpyext/test/test_bytesobject.py +++ b/pypy/module/cpyext/test/test_bytesobject.py @@ -139,6 +139,44 @@ ]) module.getstring() + def test_py_string_as_string_Unicode(self): + module = self.import_extension('foo', [ + ("getstring_unicode", "METH_NOARGS", + """ + Py_UNICODE chars[] = {'t', 'e', 's', 't'}; + PyObject* u1 = PyUnicode_FromUnicode(chars, 4); + char *buf; + buf = PyString_AsString(u1); + if (buf == NULL) + return NULL; + if (buf[3] != 't') { + PyErr_SetString(PyExc_AssertionError, "Bad conversion"); + return NULL; + } + Py_DECREF(u1); + Py_INCREF(Py_None); + return Py_None; + """), + ("getstringandsize_unicode", "METH_NOARGS", + """ + Py_UNICODE chars[] = {'t', 'e', 's', 't'}; + PyObject* u1 = PyUnicode_FromUnicode(chars, 4); + char *buf; + Py_ssize_t len; + if (PyString_AsStringAndSize(u1, &buf, &len) < 0) + return NULL; + if (len != 4) { + PyErr_SetString(PyExc_AssertionError, "Bad Length"); + return NULL; + } + Py_DECREF(u1); + Py_INCREF(Py_None); + return Py_None; + """), + ]) + module.getstring_unicode() + module.getstringandsize_unicode() + def test_format_v(self): module = self.import_extension('foo', [ ("test_string_format_v", "METH_VARARGS", diff --git a/pypy/module/cpyext/test/test_sequence.py b/pypy/module/cpyext/test/test_sequence.py --- a/pypy/module/cpyext/test/test_sequence.py +++ b/pypy/module/cpyext/test/test_sequence.py @@ -90,8 +90,10 @@ self.raises(space, api, IndexError, api.PySequence_SetItem, l, 3, w_value) + t = api.PyTuple_New(1) + api.PyTuple_SetItem(t, 0, l) self.raises(space, api, TypeError, api.PySequence_SetItem, - api.PyTuple_New(1), 0, w_value) + t, 0, w_value) self.raises(space, api, TypeError, api.PySequence_SetItem, space.newdict(), 0, w_value) diff --git a/pypy/module/cpyext/test/test_tupleobject.py b/pypy/module/cpyext/test/test_tupleobject.py --- a/pypy/module/cpyext/test/test_tupleobject.py +++ b/pypy/module/cpyext/test/test_tupleobject.py @@ -5,6 +5,7 @@ from pypy.module.cpyext.test.test_api import BaseApiTest from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase from rpython.rtyper.lltypesystem import rffi, lltype +from rpython.rlib.debug import FatalError class TestTupleObject(BaseApiTest): @@ -18,29 +19,44 @@ #assert api.PyTuple_GET_SIZE(atuple) == 3 --- now a C macro raises(TypeError, api.PyTuple_Size(space.newlist([]))) api.PyErr_Clear() - + + def test_tuple_realize_refuses_nulls(self, space, api): + py_tuple = api.PyTuple_New(1) + py.test.raises(FatalError, from_ref, space, py_tuple) + def test_tuple_resize(self, space, api): w_42 = space.wrap(42) + w_43 = space.wrap(43) + w_44 = space.wrap(44) ar = lltype.malloc(PyObjectP.TO, 1, flavor='raw') py_tuple = api.PyTuple_New(3) # inside py_tuple is an array of "PyObject *" items which each hold # a reference rffi.cast(PyTupleObject, py_tuple).c_ob_item[0] = make_ref(space, w_42) + rffi.cast(PyTupleObject, py_tuple).c_ob_item[1] = make_ref(space, w_43) ar[0] = py_tuple api._PyTuple_Resize(ar, 2) w_tuple = from_ref(space, ar[0]) assert space.int_w(space.len(w_tuple)) == 2 assert space.int_w(space.getitem(w_tuple, space.wrap(0))) == 42 + assert space.int_w(space.getitem(w_tuple, space.wrap(1))) == 43 api.Py_DecRef(ar[0]) py_tuple = api.PyTuple_New(3) rffi.cast(PyTupleObject, py_tuple).c_ob_item[0] = make_ref(space, w_42) + rffi.cast(PyTupleObject, py_tuple).c_ob_item[1] = make_ref(space, w_43) + rffi.cast(PyTupleObject, py_tuple).c_ob_item[2] = make_ref(space, w_44) ar[0] = py_tuple api._PyTuple_Resize(ar, 10) + assert api.PyTuple_Size(ar[0]) == 10 + for i in range(3, 10): + rffi.cast(PyTupleObject, py_tuple).c_ob_item[i] = make_ref( + space, space.wrap(42 + i)) w_tuple = from_ref(space, ar[0]) assert space.int_w(space.len(w_tuple)) == 10 - assert space.int_w(space.getitem(w_tuple, space.wrap(0))) == 42 + for i in range(10): + assert space.int_w(space.getitem(w_tuple, space.wrap(i))) == 42 + i api.Py_DecRef(ar[0]) lltype.free(ar, flavor='raw') diff --git a/pypy/module/cpyext/test/test_unicodeobject.py b/pypy/module/cpyext/test/test_unicodeobject.py --- a/pypy/module/cpyext/test/test_unicodeobject.py +++ b/pypy/module/cpyext/test/test_unicodeobject.py @@ -24,7 +24,7 @@ if(PyUnicode_GetSize(s) == 11) { result = 1; } - if(s->ob_type->tp_basicsize != sizeof(void*)*5) + if(s->ob_type->tp_basicsize != sizeof(void*)*7) result = 0; Py_DECREF(s); return PyBool_FromLong(result); @@ -66,6 +66,7 @@ c = PyUnicode_AsUnicode(s); c[0] = 'a'; c[1] = 0xe9; + c[2] = 0x00; c[3] = 'c'; return s; """), @@ -74,7 +75,35 @@ assert len(s) == 4 assert s == u'a�\x00c' + def test_hash(self): + module = self.import_extension('foo', [ + ("test_hash", "METH_VARARGS", + ''' + PyObject* obj = (PyTuple_GetItem(args, 0)); + long hash = ((PyUnicodeObject*)obj)->hash; + return PyLong_FromLong(hash); + ''' + ), + ]) + res = module.test_hash(u"xyz") + assert res == hash(u'xyz') + def test_default_encoded_string(self): + module = self.import_extension('foo', [ + ("test_default_encoded_string", "METH_O", + ''' + PyObject* result = _PyUnicode_AsDefaultEncodedString(args, "replace"); + Py_INCREF(result); + return result; + ''' + ), + ]) + res = module.test_default_encoded_string(u"xyz") + assert isinstance(res, str) + assert res == 'xyz' + res = module.test_default_encoded_string(u"caf\xe9") + assert isinstance(res, str) + assert res == 'caf?' class TestUnicode(BaseApiTest): def test_unicodeobject(self, space, api): @@ -155,22 +184,22 @@ def test_unicode_resize(self, space, api): py_uni = new_empty_unicode(space, 10) ar = lltype.malloc(PyObjectP.TO, 1, flavor='raw') - py_uni.c_buffer[0] = u'a' - py_uni.c_buffer[1] = u'b' - py_uni.c_buffer[2] = u'c' + py_uni.c_str[0] = u'a' + py_uni.c_str[1] = u'b' + py_uni.c_str[2] = u'c' ar[0] = rffi.cast(PyObject, py_uni) api.PyUnicode_Resize(ar, 3) py_uni = rffi.cast(PyUnicodeObject, ar[0]) assert py_uni.c_size == 3 - assert py_uni.c_buffer[1] == u'b' - assert py_uni.c_buffer[3] == u'\x00' + assert py_uni.c_str[1] == u'b' + assert py_uni.c_str[3] == u'\x00' # the same for growing ar[0] = rffi.cast(PyObject, py_uni) api.PyUnicode_Resize(ar, 10) py_uni = rffi.cast(PyUnicodeObject, ar[0]) assert py_uni.c_size == 10 - assert py_uni.c_buffer[1] == 'b' - assert py_uni.c_buffer[10] == '\x00' + assert py_uni.c_str[1] == 'b' + assert py_uni.c_str[10] == '\x00' Py_DecRef(space, ar[0]) lltype.free(ar, flavor='raw') diff --git a/pypy/module/cpyext/tupleobject.py b/pypy/module/cpyext/tupleobject.py --- a/pypy/module/cpyext/tupleobject.py +++ b/pypy/module/cpyext/tupleobject.py @@ -1,5 +1,6 @@ from pypy.interpreter.error import OperationError from rpython.rtyper.lltypesystem import rffi, lltype +from rpython.rlib.debug import fatalerror_notb from pypy.module.cpyext.api import (cpython_api, Py_ssize_t, CANNOT_FAIL, build_type_checkers, PyObjectFields, cpython_struct, bootstrap_function) @@ -91,14 +92,22 @@ def tuple_realize(space, py_obj): """ Creates the tuple in the interpreter. The PyTupleObject must not - be modified after this call. + be modified after this call. We check that it does not contain + any NULLs at this point (which would correspond to half-broken + W_TupleObjects). """ py_tup = rffi.cast(PyTupleObject, py_obj) l = py_tup.c_ob_size p = py_tup.c_ob_item items_w = [None] * l for i in range(l): - items_w[i] = from_ref(space, p[i]) + w_item = from_ref(space, p[i]) + if w_item is None: + fatalerror_notb( + "Fatal error in cpyext, CPython compatibility layer: " + "converting a PyTupleObject into a W_TupleObject, " + "but found NULLs as items") + items_w[i] = w_item w_obj = space.newtuple(items_w) track_reference(space, py_obj, w_obj) return w_obj diff --git a/pypy/module/cpyext/unicodeobject.py b/pypy/module/cpyext/unicodeobject.py --- a/pypy/module/cpyext/unicodeobject.py +++ b/pypy/module/cpyext/unicodeobject.py @@ -22,7 +22,8 @@ PyUnicodeObjectStruct = lltype.ForwardReference() PyUnicodeObject = lltype.Ptr(PyUnicodeObjectStruct) PyUnicodeObjectFields = (PyObjectFields + - (("buffer", rffi.CWCHARP), ("size", Py_ssize_t))) + (("str", rffi.CWCHARP), ("size", Py_ssize_t), + ("hash", rffi.LONG), ("defenc", PyObject))) cpython_struct("PyUnicodeObject", PyUnicodeObjectFields, PyUnicodeObjectStruct) @bootstrap_function @@ -54,16 +55,20 @@ buflen = length + 1 py_uni.c_size = length - py_uni.c_buffer = lltype.malloc(rffi.CWCHARP.TO, buflen, - flavor='raw', zero=True, - add_memory_pressure=True) + py_uni.c_str = lltype.malloc(rffi.CWCHARP.TO, buflen, + flavor='raw', zero=True, + add_memory_pressure=True) + py_uni.c_hash = -1 + py_uni.c_defenc = lltype.nullptr(PyObject.TO) return py_uni def unicode_attach(space, py_obj, w_obj): "Fills a newly allocated PyUnicodeObject with a unicode string" py_unicode = rffi.cast(PyUnicodeObject, py_obj) py_unicode.c_size = len(space.unicode_w(w_obj)) - py_unicode.c_buffer = lltype.nullptr(rffi.CWCHARP.TO) + py_unicode.c_str = lltype.nullptr(rffi.CWCHARP.TO) + py_unicode.c_hash = space.hash_w(w_obj) + py_unicode.c_defenc = lltype.nullptr(PyObject.TO) def unicode_realize(space, py_obj): """ @@ -71,17 +76,20 @@ be modified after this call. """ py_uni = rffi.cast(PyUnicodeObject, py_obj) - s = rffi.wcharpsize2unicode(py_uni.c_buffer, py_uni.c_size) + s = rffi.wcharpsize2unicode(py_uni.c_str, py_uni.c_size) w_obj = space.wrap(s) + py_uni.c_hash = space.hash_w(w_obj) track_reference(space, py_obj, w_obj) return w_obj @cpython_api([PyObject], lltype.Void, header=None) def unicode_dealloc(space, py_obj): py_unicode = rffi.cast(PyUnicodeObject, py_obj) - if py_unicode.c_buffer: - lltype.free(py_unicode.c_buffer, flavor="raw") + if py_unicode.c_str: + lltype.free(py_unicode.c_str, flavor="raw") from pypy.module.cpyext.object import PyObject_dealloc + if py_unicode.c_defenc: + PyObject_dealloc(space, py_unicode.c_defenc) PyObject_dealloc(space, py_obj) @cpython_api([Py_UNICODE], rffi.INT_real, error=CANNOT_FAIL) @@ -205,12 +213,12 @@ """Return a pointer to the internal Py_UNICODE buffer of the object. ref has to be a PyUnicodeObject (not checked).""" ref_unicode = rffi.cast(PyUnicodeObject, ref) - if not ref_unicode.c_buffer: + if not ref_unicode.c_str: # Copy unicode buffer w_unicode = from_ref(space, ref) u = space.unicode_w(w_unicode) - ref_unicode.c_buffer = rffi.unicode2wcharp(u) - return ref_unicode.c_buffer + ref_unicode.c_str = rffi.unicode2wcharp(u) + return ref_unicode.c_str @cpython_api([PyObject], rffi.CWCHARP) def PyUnicode_AsUnicode(space, ref): @@ -241,7 +249,7 @@ string may or may not be 0-terminated. It is the responsibility of the caller to make sure that the wchar_t string is 0-terminated in case this is required by the application.""" - c_buffer = PyUnicode_AS_UNICODE(space, rffi.cast(PyObject, ref)) + c_str = PyUnicode_AS_UNICODE(space, rffi.cast(PyObject, ref)) c_size = ref.c_size # If possible, try to copy the 0-termination as well @@ -251,7 +259,7 @@ i = 0 while i < size: - buf[i] = c_buffer[i] + buf[i] = c_str[i] i += 1 if size > c_size: @@ -343,8 +351,15 @@ return PyUnicode_FromUnicode(space, wchar_p, length) @cpython_api([PyObject, CONST_STRING], PyObject) -def _PyUnicode_AsDefaultEncodedString(space, w_unicode, errors): - return PyUnicode_AsEncodedString(space, w_unicode, lltype.nullptr(rffi.CCHARP.TO), errors) +def _PyUnicode_AsDefaultEncodedString(space, ref, errors): + # Returns a borrowed reference. + py_uni = rffi.cast(PyUnicodeObject, ref) + if not py_uni.c_defenc: + py_uni.c_defenc = make_ref( + space, PyUnicode_AsEncodedString( + space, ref, + lltype.nullptr(rffi.CCHARP.TO), errors)) + return py_uni.c_defenc @cpython_api([CONST_STRING, Py_ssize_t, CONST_STRING, CONST_STRING], PyObject) def PyUnicode_Decode(space, s, size, encoding, errors): @@ -444,7 +459,7 @@ def PyUnicode_Resize(space, ref, newsize): # XXX always create a new string so far py_uni = rffi.cast(PyUnicodeObject, ref[0]) - if not py_uni.c_buffer: + if not py_uni.c_str: raise OperationError(space.w_SystemError, space.wrap( "PyUnicode_Resize called on already created string")) try: @@ -458,7 +473,7 @@ if oldsize < newsize: to_cp = oldsize for i in range(to_cp): - py_newuni.c_buffer[i] = py_uni.c_buffer[i] + py_newuni.c_str[i] = py_uni.c_str[i] Py_DecRef(space, ref[0]) ref[0] = rffi.cast(PyObject, py_newuni) return 0 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 @@ -502,29 +502,34 @@ return W_NDimArray(self.implementation.transpose(self, axes)) def descr_transpose(self, space, args_w): - if len(args_w) == 1 and space.isinstance_w(args_w[0], space.w_tuple): - args_w = space.fixedview(args_w[0]) - if (len(args_w) == 0 or - len(args_w) == 1 and space.is_none(args_w[0])): + if len(args_w) == 0 or len(args_w) == 1 and space.is_none(args_w[0]): return self.descr_get_transpose(space) else: - if len(args_w) != self.ndims(): - raise oefmt(space.w_ValueError, "axes don't match array") - axes = [] - axes_seen = [False] * self.ndims() - for w_arg in args_w: - try: - axis = support.index_w(space, w_arg) - except OperationError: - raise oefmt(space.w_TypeError, "an integer is required") - if axis < 0 or axis >= self.ndims(): - raise oefmt(space.w_ValueError, "invalid axis for this array") - if axes_seen[axis] is True: - raise oefmt(space.w_ValueError, "repeated axis in transpose") - axes.append(axis) - axes_seen[axis] = True - return self.descr_get_transpose(space, axes) + if len(args_w) > 1: + axes = args_w + else: # Iterable in the only argument (len(arg_w) == 1 and arg_w[0] is not None) + axes = space.fixedview(args_w[0]) + axes = self._checked_axes(axes, space) + return self.descr_get_transpose(space, axes) + + def _checked_axes(self, axes_raw, space): + if len(axes_raw) != self.ndims(): + raise oefmt(space.w_ValueError, "axes don't match array") + axes = [] + axes_seen = [False] * self.ndims() + for elem in axes_raw: + try: + axis = support.index_w(space, elem) + except OperationError: + raise oefmt(space.w_TypeError, "an integer is required") + if axis < 0 or axis >= self.ndims(): + raise oefmt(space.w_ValueError, "invalid axis for this array") + if axes_seen[axis] is True: + raise oefmt(space.w_ValueError, "repeated axis in transpose") + axes.append(axis) + axes_seen[axis] = True + return axes @unwrap_spec(axis1=int, axis2=int) def descr_swapaxes(self, space, axis1, axis2): diff --git a/pypy/module/micronumpy/test/test_ndarray.py b/pypy/module/micronumpy/test/test_ndarray.py --- a/pypy/module/micronumpy/test/test_ndarray.py +++ b/pypy/module/micronumpy/test/test_ndarray.py @@ -2960,6 +2960,36 @@ assert (a.transpose() == b).all() assert (a.transpose(None) == b).all() + def test_transpose_arg_tuple(self): + import numpy as np + a = np.arange(24).reshape(2, 3, 4) + transpose_args = a.transpose(1, 2, 0) + + transpose_test = a.transpose((1, 2, 0)) + + assert transpose_test.shape == (3, 4, 2) + assert (transpose_args == transpose_test).all() + + def test_transpose_arg_list(self): + import numpy as np + a = np.arange(24).reshape(2, 3, 4) + transpose_args = a.transpose(1, 2, 0) + + transpose_test = a.transpose([1, 2, 0]) + + assert transpose_test.shape == (3, 4, 2) + assert (transpose_args == transpose_test).all() + + def test_transpose_arg_array(self): + import numpy as np + a = np.arange(24).reshape(2, 3, 4) + transpose_args = a.transpose(1, 2, 0) + + transpose_test = a.transpose(np.array([1, 2, 0])) + + assert transpose_test.shape == (3, 4, 2) + assert (transpose_args == transpose_test).all() + def test_transpose_error(self): import numpy as np a = np.arange(24).reshape(2, 3, 4) @@ -2968,6 +2998,11 @@ raises(ValueError, a.transpose, 1, 0, 1) raises(TypeError, a.transpose, 1, 0, '2') + def test_transpose_unexpected_argument(self): + import numpy as np + a = np.array([[1, 2], [3, 4], [5, 6]]) + raises(TypeError, 'a.transpose(axes=(1,2,0))') + def test_flatiter(self): from numpy import array, flatiter, arange, zeros a = array([[10, 30], [40, 60]]) diff --git a/pypy/module/operator/app_operator.py b/pypy/module/operator/app_operator.py --- a/pypy/module/operator/app_operator.py +++ b/pypy/module/operator/app_operator.py @@ -79,54 +79,45 @@ else: return _resolve_attr_chain(chain, obj, idx + 1) - -class _simple_attrgetter(object): - def __init__(self, attr): - self._attr = attr +class attrgetter(object): + def __init__(self, attr, *attrs): + if ( + not isinstance(attr, basestring) or + not all(isinstance(a, basestring) for a in attrs) + ): + def _raise_typeerror(obj): + raise TypeError( + "argument must be a string, not %r" % type(attr).__name__ + ) + self._call = _raise_typeerror + elif attrs: + self._multi_attrs = [ + a.split(".") for a in [attr] + list(attrs) + ] + self._call = self._multi_attrgetter + elif "." not in attr: + self._simple_attr = attr + self._call = self._simple_attrgetter + else: + self._single_attr = attr.split(".") + self._call = self._single_attrgetter def __call__(self, obj): - return getattr(obj, self._attr) + return self._call(obj) + def _simple_attrgetter(self, obj): + return getattr(obj, self._simple_attr) -class _single_attrgetter(object): - def __init__(self, attrs): - self._attrs = attrs + def _single_attrgetter(self, obj): + return _resolve_attr_chain(self._single_attr, obj) - def __call__(self, obj): - return _resolve_attr_chain(self._attrs, obj) - - -class _multi_attrgetter(object): - def __init__(self, attrs): - self._attrs = attrs - - def __call__(self, obj): + def _multi_attrgetter(self, obj): return tuple([ _resolve_attr_chain(attrs, obj) - for attrs in self._attrs + for attrs in self._multi_attrs ]) -def attrgetter(attr, *attrs): - if ( - not isinstance(attr, basestring) or - not all(isinstance(a, basestring) for a in attrs) - ): - def _raise_typeerror(obj): - raise TypeError( - "argument must be a string, not %r" % type(attr).__name__ - ) - return _raise_typeerror - if attrs: - return _multi_attrgetter([ - a.split(".") for a in [attr] + list(attrs) - ]) - elif "." not in attr: - return _simple_attrgetter(attr) - else: - return _single_attrgetter(attr.split(".")) - - class itemgetter(object): def __init__(self, item, *items): self._single = not bool(items) diff --git a/pypy/module/operator/test/test_operator.py b/pypy/module/operator/test/test_operator.py --- a/pypy/module/operator/test/test_operator.py +++ b/pypy/module/operator/test/test_operator.py @@ -47,7 +47,13 @@ a.name = "hello" a.child = A() a.child.name = "world" + a.child.foo = "bar" assert attrgetter("child.name")(a) == "world" + assert attrgetter("child.name", "child.foo")(a) == ("world", "bar") + + def test_attrgetter_type(self): + from operator import attrgetter + assert type(attrgetter("child.name")) is attrgetter def test_concat(self): class Seq1: diff --git a/pypy/module/test_lib_pypy/ctypes_tests/test_anon.py b/pypy/module/test_lib_pypy/ctypes_tests/test_anon.py --- a/pypy/module/test_lib_pypy/ctypes_tests/test_anon.py +++ b/pypy/module/test_lib_pypy/ctypes_tests/test_anon.py @@ -57,3 +57,32 @@ assert Y.y.offset == sizeof(c_int) * 2 assert Y._names_ == ['x', 'a', 'b', 'y'] + + def test_anonymous_fields_on_instance(self): + # this is about the *instance-level* access of anonymous fields, + # which you'd guess is the most common, but used not to work + # (issue #2230) + + class B(Structure): + _fields_ = [("x", c_int), ("y", c_int), ("z", c_int)] + class A(Structure): + _anonymous_ = ["b"] + _fields_ = [("b", B)] + + a = A() + a.x = 5 + assert a.x == 5 + assert a.b.x == 5 + a.b.x += 1 + assert a.x == 6 + + class C(Structure): + _anonymous_ = ["a"] + _fields_ = [("v", c_int), ("a", A)] + + c = C() + c.v = 3 + c.y = -8 + assert c.v == 3 + assert c.y == c.a.y == c.a.b.y == -8 + assert not hasattr(c, 'b') diff --git a/pypy/module/test_lib_pypy/pyrepl/infrastructure.py b/pypy/module/test_lib_pypy/pyrepl/infrastructure.py --- a/pypy/module/test_lib_pypy/pyrepl/infrastructure.py +++ b/pypy/module/test_lib_pypy/pyrepl/infrastructure.py @@ -18,6 +18,9 @@ # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. from __future__ import print_function +from contextlib import contextmanager +import os + from pyrepl.reader import Reader from pyrepl.console import Console, Event @@ -71,3 +74,14 @@ con = TestConsole(test_spec, verbose=True) reader = reader_class(con) reader.readline() + + +@contextmanager +def sane_term(): + """Ensure a TERM that supports clear""" + old_term, os.environ['TERM'] = os.environ.get('TERM'), 'xterm' + yield + if old_term is not None: + os.environ['TERM'] = old_term + else: + del os.environ['TERM'] diff --git a/pypy/module/test_lib_pypy/pyrepl/test_bugs.py b/pypy/module/test_lib_pypy/pyrepl/test_bugs.py --- a/pypy/module/test_lib_pypy/pyrepl/test_bugs.py +++ b/pypy/module/test_lib_pypy/pyrepl/test_bugs.py @@ -18,7 +18,7 @@ # CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. from pyrepl.historical_reader import HistoricalReader -from .infrastructure import EA, BaseTestReader, read_spec +from .infrastructure import EA, BaseTestReader, sane_term, read_spec # this test case should contain as-verbatim-as-possible versions of # (applicable) bug reports @@ -46,7 +46,8 @@ read_spec(spec, HistoricalTestReader) -@pytest.mark.skipif("os.name != 'posix' or 'darwin' in sys.platform") +@pytest.mark.skipif("os.name != 'posix' or 'darwin' in sys.platform or " + "'kfreebsd' in sys.platform") def test_signal_failure(monkeypatch): import os import pty @@ -61,13 +62,14 @@ mfd, sfd = pty.openpty() try: - c = UnixConsole(sfd, sfd) - c.prepare() - c.restore() - monkeypatch.setattr(signal, 'signal', failing_signal) - c.prepare() - monkeypatch.setattr(signal, 'signal', really_failing_signal) - c.restore() + with sane_term(): + c = UnixConsole(sfd, sfd) + c.prepare() + c.restore() + monkeypatch.setattr(signal, 'signal', failing_signal) + c.prepare() + monkeypatch.setattr(signal, 'signal', really_failing_signal) + c.restore() finally: os.close(mfd) os.close(sfd) diff --git a/pypy/module/test_lib_pypy/pyrepl/test_readline.py b/pypy/module/test_lib_pypy/pyrepl/test_readline.py --- a/pypy/module/test_lib_pypy/pyrepl/test_readline.py +++ b/pypy/module/test_lib_pypy/pyrepl/test_readline.py @@ -1,7 +1,10 @@ import pytest +from .infrastructure import sane_term -@pytest.mark.skipif("os.name != 'posix' or 'darwin' in sys.platform") + +@pytest.mark.skipif("os.name != 'posix' or 'darwin' in sys.platform or " + "'kfreebsd' in sys.platform") def test_raw_input(): import os import pty @@ -11,7 +14,8 @@ readline_wrapper = _ReadlineWrapper(slave, slave) os.write(master, b'input\n') - result = readline_wrapper.get_reader().readline() + with sane_term(): + result = readline_wrapper.get_reader().readline() #result = readline_wrapper.raw_input('prompt:') assert result == 'input' # A bytes string on python2, a unicode string on python3. diff --git a/pypy/objspace/std/objectobject.py b/pypy/objspace/std/objectobject.py --- a/pypy/objspace/std/objectobject.py +++ b/pypy/objspace/std/objectobject.py @@ -110,7 +110,7 @@ def descr__init__(space, w_obj, __args__): # don't allow arguments unless __new__ is overridden w_type = space.type(w_obj) - w_parent_new, _ = w_type.lookup_where('__new__') + w_parent_new, _ = space.lookup_in_type_where(w_type, '__new__') if w_parent_new is space.w_object: try: __args__.fixedunpack(0) diff --git a/pypy/tool/gdb_pypy.py b/pypy/tool/gdb_pypy.py --- a/pypy/tool/gdb_pypy.py +++ b/pypy/tool/gdb_pypy.py @@ -288,9 +288,11 @@ RPyListPrinter.recursive = True try: itemlist = [] - for i in range(length): + for i in range(min(length, MAX_DISPLAY_LENGTH)): item = items[i] itemlist.append(str(item)) # may recurse here + if length > MAX_DISPLAY_LENGTH: + itemlist.append("...") str_items = ', '.join(itemlist) finally: RPyListPrinter.recursive = False diff --git a/requirements.txt b/requirements.txt --- a/requirements.txt +++ b/requirements.txt @@ -1,4 +1,3 @@ # hypothesis is used for test generation on untranslated jit tests hypothesis -enum>=0.4.6 # is a dependency, but old pip does not pick it up enum34>=1.1.2 diff --git a/rpython/config/translationoption.py b/rpython/config/translationoption.py --- a/rpython/config/translationoption.py +++ b/rpython/config/translationoption.py @@ -126,6 +126,9 @@ ChoiceOption("jit_profiler", "integrate profiler support into the JIT", ["off", "oprofile"], default="off"), + ChoiceOption("jit_opencoder_model", "the model limits the maximal length" + " of traces. Use big if you want to go bigger than " + "the default", ["big", "normal"], default="normal"), BoolOption("check_str_without_nul", "Forbid NUL chars in strings in some external function calls", default=False, cmdline=None), diff --git a/rpython/flowspace/specialcase.py b/rpython/flowspace/specialcase.py --- a/rpython/flowspace/specialcase.py +++ b/rpython/flowspace/specialcase.py @@ -77,6 +77,7 @@ for c in s: buf.append(c) buf.append(' ') +rpython_print_item._annenforceargs_ = (str,) def rpython_print_newline(): buf = stdoutbuffer.linebuf 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 @@ -14,7 +14,7 @@ CoreRegisterManager, check_imm_arg, VFPRegisterManager, operations as regalloc_operations) from rpython.jit.backend.llsupport import jitframe, rewrite -from rpython.jit.backend.llsupport.assembler import DEBUG_COUNTER, debug_bridge, BaseAssembler +from rpython.jit.backend.llsupport.assembler import DEBUG_COUNTER, BaseAssembler from rpython.jit.backend.llsupport.regalloc import get_scale, valid_addressing_size from rpython.jit.backend.llsupport.asmmemmgr import MachineDataBlockWrapper from rpython.jit.backend.model import CompiledLoopToken @@ -481,8 +481,9 @@ def generate_quick_failure(self, guardtok): startpos = self.mc.currpos() - fail_descr, target = self.store_info_on_descr(startpos, guardtok) - self.regalloc_push(imm(fail_descr)) + faildescrindex, target = self.store_info_on_descr(startpos, guardtok) + self.load_from_gc_table(r.ip.value, faildescrindex) + self.regalloc_push(r.ip) self.push_gcmap(self.mc, gcmap=guardtok.gcmap, push=True) self.mc.BL(target) return startpos @@ -556,7 +557,7 @@ debug_stop('jit-backend-ops') def _call_header(self): - assert self.mc.currpos() == 0 + # there is the gc table before this point self.gen_func_prolog() def _call_header_with_stack_check(self): @@ -596,20 +597,22 @@ frame_info = self.datablockwrapper.malloc_aligned( jitframe.JITFRAMEINFO_SIZE, alignment=WORD) clt.frame_info = rffi.cast(jitframe.JITFRAMEINFOPTR, frame_info) - clt.allgcrefs = [] clt.frame_info.clear() # for now if log: operations = self._inject_debugging_code(looptoken, operations, 'e', looptoken.number) + regalloc = Regalloc(assembler=self) + allgcrefs = [] + operations = regalloc.prepare_loop(inputargs, operations, looptoken, + allgcrefs) + self.reserve_gcref_table(allgcrefs) + functionpos = self.mc.get_relative_pos() + self._call_header_with_stack_check() self._check_frame_depth_debug(self.mc) - regalloc = Regalloc(assembler=self) - operations = regalloc.prepare_loop(inputargs, operations, looptoken, - clt.allgcrefs) - loop_head = self.mc.get_relative_pos() looptoken._ll_loop_code = loop_head # @@ -620,9 +623,11 @@ self.write_pending_failure_recoveries() + full_size = self.mc.get_relative_pos() rawstart = self.materialize_loop(looptoken) - looptoken._function_addr = looptoken._ll_function_addr = rawstart + looptoken._ll_function_addr = rawstart + functionpos + self.patch_gcref_table(looptoken, rawstart) self.process_pending_guards(rawstart) self.fixup_target_tokens(rawstart) @@ -641,7 +646,13 @@ looptoken.number, loopname, r_uint(rawstart + loop_head), r_uint(rawstart + size_excluding_failure_stuff), - r_uint(rawstart))) + r_uint(rawstart + functionpos))) + debug_print(" gc table: 0x%x" % r_uint(rawstart)) + debug_print(" function: 0x%x" % r_uint(rawstart + functionpos)) + debug_print(" resops: 0x%x" % r_uint(rawstart + loop_head)) + debug_print(" failures: 0x%x" % r_uint(rawstart + + size_excluding_failure_stuff)) + debug_print(" end: 0x%x" % r_uint(rawstart + full_size)) debug_stop("jit-backend-addr") return AsmInfo(ops_offset, rawstart + loop_head, @@ -678,27 +689,43 @@ arglocs = self.rebuild_faillocs_from_descr(faildescr, inputargs) regalloc = Regalloc(assembler=self) - startpos = self.mc.get_relative_pos() + allgcrefs = [] operations = regalloc.prepare_bridge(inputargs, arglocs, operations, - self.current_clt.allgcrefs, + allgcrefs, self.current_clt.frame_info) + self.reserve_gcref_table(allgcrefs) + startpos = self.mc.get_relative_pos() self._check_frame_depth(self.mc, regalloc.get_gcmap()) + bridgestartpos = self.mc.get_relative_pos() frame_depth_no_fixed_size = self._assemble(regalloc, inputargs, operations) codeendpos = self.mc.get_relative_pos() self.write_pending_failure_recoveries() + fullsize = self.mc.get_relative_pos() rawstart = self.materialize_loop(original_loop_token) + self.patch_gcref_table(original_loop_token, rawstart) self.process_pending_guards(rawstart) + debug_start("jit-backend-addr") + debug_print("bridge out of Guard 0x%x has address 0x%x to 0x%x" % + (r_uint(descr_number), r_uint(rawstart + startpos), + r_uint(rawstart + codeendpos))) + debug_print(" gc table: 0x%x" % r_uint(rawstart)) + debug_print(" jump target: 0x%x" % r_uint(rawstart + startpos)) + debug_print(" resops: 0x%x" % r_uint(rawstart + bridgestartpos)) + debug_print(" failures: 0x%x" % r_uint(rawstart + codeendpos)) + debug_print(" end: 0x%x" % r_uint(rawstart + fullsize)) + debug_stop("jit-backend-addr") + # patch the jump from original guard self.patch_trace(faildescr, original_loop_token, - rawstart, regalloc) + rawstart + startpos, regalloc) self.patch_stack_checks(frame_depth_no_fixed_size + JITFRAME_FIXED_SIZE, rawstart) @@ -716,9 +743,53 @@ ops_offset=ops_offset) self.teardown() - debug_bridge(descr_number, rawstart, codeendpos) + return AsmInfo(ops_offset, startpos + rawstart, codeendpos - startpos) - return AsmInfo(ops_offset, startpos + rawstart, codeendpos - startpos) + def reserve_gcref_table(self, allgcrefs): + gcref_table_size = len(allgcrefs) * WORD + # align to a multiple of 16 and reserve space at the beginning + # of the machine code for the gc table. This lets us write + # machine code with relative addressing (see load_from_gc_table()) + gcref_table_size = (gcref_table_size + 15) & ~15 + mc = self.mc + assert mc.get_relative_pos() == 0 + for i in range(gcref_table_size): + mc.writechar('\x00') + self.setup_gcrefs_list(allgcrefs) + + def patch_gcref_table(self, looptoken, rawstart): + # the gc table is at the start of the machine code. Fill it now + tracer = self.cpu.gc_ll_descr.make_gcref_tracer(rawstart, + self._allgcrefs) + gcreftracers = self.get_asmmemmgr_gcreftracers(looptoken) + gcreftracers.append(tracer) # keepalive + self.teardown_gcrefs_list() + + def load_from_gc_table(self, regnum, index): + """emits either: + LDR Rt, [PC, #offset] if -4095 <= offset + or: + gen_load_int(Rt, offset) + LDR Rt, [PC, Rt] for larger offsets + """ + mc = self.mc + address_in_buffer = index * WORD # at the start of the buffer + offset = address_in_buffer - (mc.get_relative_pos() + 8) # negative + if offset >= -4095: + mc.LDR_ri(regnum, r.pc.value, offset) + else: + # The offset we're loading is negative: right now, + # gen_load_int() will always use exactly + # get_max_size_of_gen_load_int() instructions. No point + # in optimizing in case we get less. Just in case though, + # we check and pad with nops. + extra_bytes = mc.get_max_size_of_gen_load_int() * 2 + offset -= extra_bytes + start = mc.get_relative_pos() + mc.gen_load_int(regnum, offset) + while mc.get_relative_pos() != start + extra_bytes: + mc.NOP() + mc.LDR_rr(regnum, r.pc.value, regnum) def new_stack_loc(self, i, tp): base_ofs = self.cpu.get_baseofs_of_frame_field() @@ -929,6 +1000,12 @@ clt.asmmemmgr_blocks = [] return clt.asmmemmgr_blocks + def get_asmmemmgr_gcreftracers(self, looptoken): + clt = looptoken.compiled_loop_token + if clt.asmmemmgr_gcreftracers is None: + clt.asmmemmgr_gcreftracers = [] + return clt.asmmemmgr_gcreftracers + def _walk_operations(self, inputargs, operations, regalloc): fcond = c.AL self._regalloc = regalloc @@ -939,9 +1016,9 @@ op = operations[i] self.mc.mark_op(op) opnum = op.getopnum() - if op.has_no_side_effect() and op not in regalloc.longevity: + if rop.has_no_side_effect(opnum) and op not in regalloc.longevity: regalloc.possibly_free_vars_for_op(op) - elif not we_are_translated() and op.getopnum() == -127: + elif not we_are_translated() and op.getopnum() == rop.FORCE_SPILL: regalloc.prepare_force_spill(op, fcond) else: arglocs = regalloc_operations[opnum](regalloc, op, fcond) @@ -949,7 +1026,7 @@ fcond = asm_operations[opnum](self, op, arglocs, regalloc, fcond) assert fcond is not None - if op.is_guard(): + if rop.is_guard(opnum): regalloc.possibly_free_vars(op.getfailargs()) if op.type != 'v': regalloc.possibly_free_var(op) diff --git a/rpython/jit/backend/arm/detect.py b/rpython/jit/backend/arm/detect.py --- a/rpython/jit/backend/arm/detect.py +++ b/rpython/jit/backend/arm/detect.py @@ -63,3 +63,44 @@ "falling back to", "ARMv%d" % n) debug_stop("jit-backend-arch") return n + + +# Once we can rely on the availability of glibc >= 2.16, replace this with: +# from rpython.rtyper.lltypesystem import lltype, rffi +# getauxval = rffi.llexternal("getauxval", [lltype.Unsigned], lltype.Unsigned) +def getauxval(type_, filename='/proc/self/auxv'): + fd = os.open(filename, os.O_RDONLY, 0644) + + buf_size = 2048 + struct_size = 8 # 2x uint32 + try: + buf = os.read(fd, buf_size) + finally: + os.close(fd) + + # decode chunks of 8 bytes (a_type, a_val), and + # return the a_val whose a_type corresponds to type_, + # or zero if not found. + i = 0 + while i <= buf_size - struct_size: + # We only support little-endian ARM + a_type = (ord(buf[i]) | + (ord(buf[i+1]) << 8) | + (ord(buf[i+2]) << 16) | + (ord(buf[i+3]) << 24)) + a_val = (ord(buf[i+4]) | + (ord(buf[i+5]) << 8) | + (ord(buf[i+6]) << 16) | + (ord(buf[i+7]) << 24)) + i += struct_size + if a_type == type_: + return a_val + + return 0 + + +def detect_neon(): + AT_HWCAP = 16 + HWCAP_NEON = 1 << 12 + hwcap = getauxval(AT_HWCAP) + return bool(hwcap & HWCAP_NEON) 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 @@ -35,9 +35,9 @@ class ArmGuardToken(GuardToken): def __init__(self, cpu, gcmap, faildescr, failargs, fail_locs, - offset, guard_opnum, frame_depth, fcond=c.AL): + offset, guard_opnum, frame_depth, faildescrindex, fcond=c.AL): GuardToken.__init__(self, cpu, gcmap, faildescr, failargs, fail_locs, - guard_opnum, frame_depth) + guard_opnum, frame_depth, faildescrindex) self.fcond = fcond self.offset = offset @@ -178,6 +178,7 @@ assert isinstance(descr, AbstractFailDescr) gcmap = allocate_gcmap(self, frame_depth, JITFRAME_FIXED_SIZE) + faildescrindex = self.get_gcref_from_faildescr(descr) token = ArmGuardToken(self.cpu, gcmap, descr, failargs=op.getfailargs(), @@ -185,6 +186,7 @@ offset=offset, guard_opnum=op.getopnum(), frame_depth=frame_depth, + faildescrindex=faildescrindex, fcond=fcond) return token @@ -398,14 +400,13 @@ def emit_op_finish(self, op, arglocs, regalloc, fcond): base_ofs = self.cpu.get_baseofs_of_frame_field() - if len(arglocs) == 2: - [return_val, fail_descr_loc] = arglocs + if len(arglocs) > 0: + [return_val] = arglocs self.store_reg(self.mc, return_val, r.fp, base_ofs) - else: - [fail_descr_loc] = arglocs ofs = self.cpu.get_ofs_of_frame_field('jf_descr') - self.mc.gen_load_int(r.ip.value, fail_descr_loc.value) + faildescrindex = self.get_gcref_from_faildescr(op.getdescr()) + self.load_from_gc_table(r.ip.value, faildescrindex) # XXX self.mov(fail_descr_loc, RawStackLoc(ofs)) self.store_reg(self.mc, r.ip, r.fp, ofs, helper=r.lr) if op.numargs() > 0 and op.getarg(0).type == REF: @@ -1035,9 +1036,9 @@ assert (guard_op.getopnum() == rop.GUARD_NOT_FORCED or guard_op.getopnum() == rop.GUARD_NOT_FORCED_2) faildescr = guard_op.getdescr() + faildescrindex = self.get_gcref_from_faildescr(faildescr) ofs = self.cpu.get_ofs_of_frame_field('jf_force_descr') - value = rffi.cast(lltype.Signed, cast_instance_to_gcref(faildescr)) - self.mc.gen_load_int(r.ip.value, value) + self.load_from_gc_table(r.ip.value, faildescrindex) self.store_reg(self.mc, r.ip, r.fp, ofs) def _find_nearby_operation(self, delta): @@ -1092,8 +1093,8 @@ self.mc.VCVT_int_to_float(res.value, r.svfp_ip.value) return fcond - # the following five instructions are only ARMv7; - # regalloc.py won't call them at all on ARMv6 + # the following five instructions are only ARMv7 with NEON; + # regalloc.py won't call them at all, in other cases emit_opx_llong_add = gen_emit_float_op('llong_add', 'VADD_i64') emit_opx_llong_sub = gen_emit_float_op('llong_sub', 'VSUB_i64') emit_opx_llong_and = gen_emit_float_op('llong_and', 'VAND_i64') @@ -1250,3 +1251,9 @@ self._load_from_mem(res_loc, res_loc, ofs_loc, imm(scale), signed, fcond) return fcond + + def emit_op_load_from_gc_table(self, op, arglocs, regalloc, fcond): + res_loc, = arglocs + index = op.getarg(0).getint() + self.load_from_gc_table(res_loc.value, index) + return fcond 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 @@ -1,5 +1,4 @@ from rpython.rtyper.annlowlevel import cast_instance_to_gcref -from rpython.rlib import rgc from rpython.rlib.debug import debug_print, debug_start, debug_stop from rpython.jit.backend.llsupport.regalloc import FrameManager, \ RegisterManager, TempVar, compute_vars_longevity, BaseRegalloc, \ @@ -530,7 +529,7 @@ EffectInfo.OS_LLONG_AND, EffectInfo.OS_LLONG_OR, EffectInfo.OS_LLONG_XOR): - if self.cpu.cpuinfo.arch_version >= 7: + if self.cpu.cpuinfo.neon: args = self._prepare_llong_binop_xx(op, fcond) self.perform_extra(op, args, fcond) return @@ -627,16 +626,11 @@ def prepare_op_finish(self, op, fcond): # the frame is in fp, but we have to point where in the frame is # the potential argument to FINISH - descr = op.getdescr() - fail_descr = cast_instance_to_gcref(descr) - # we know it does not move, but well - rgc._make_sure_does_not_move(fail_descr) - fail_descr = rffi.cast(lltype.Signed, fail_descr) if op.numargs() == 1: loc = self.make_sure_var_in_reg(op.getarg(0)) - locs = [loc, imm(fail_descr)] + locs = [loc] else: - locs = [imm(fail_descr)] + locs = [] return locs def load_condition_into_cc(self, box): @@ -892,6 +886,10 @@ prepare_op_same_as_r = _prepare_op_same_as prepare_op_same_as_f = _prepare_op_same_as + def prepare_op_load_from_gc_table(self, op, fcond): + resloc = self.force_allocate_reg(op) + return [resloc] + def prepare_op_call_malloc_nursery(self, op, fcond): size_box = op.getarg(0) assert isinstance(size_box, ConstInt) diff --git a/rpython/jit/backend/arm/runner.py b/rpython/jit/backend/arm/runner.py --- a/rpython/jit/backend/arm/runner.py +++ b/rpython/jit/backend/arm/runner.py @@ -7,13 +7,14 @@ from rpython.rlib.jit_hooks import LOOP_RUN_CONTAINER from rpython.rtyper.lltypesystem import lltype, llmemory from rpython.jit.backend.arm.detect import detect_hardfloat -from rpython.jit.backend.arm.detect import detect_arch_version +from rpython.jit.backend.arm.detect import detect_arch_version, detect_neon jitframe.STATICSIZE = JITFRAME_FIXED_SIZE class CPUInfo(object): hf_abi = False arch_version = 6 + neon = False class AbstractARMCPU(AbstractLLCPU): @@ -48,6 +49,7 @@ def setup_once(self): self.cpuinfo.arch_version = detect_arch_version() self.cpuinfo.hf_abi = detect_hardfloat() + self.cpuinfo.neon = detect_neon() #self.codemap.setup() self.assembler.setup_once() diff --git a/rpython/jit/backend/arm/test/test_detect.py b/rpython/jit/backend/arm/test/test_detect.py --- a/rpython/jit/backend/arm/test/test_detect.py +++ b/rpython/jit/backend/arm/test/test_detect.py @@ -1,6 +1,6 @@ import py from rpython.tool.udir import udir -from rpython.jit.backend.arm.detect import detect_arch_version +from rpython.jit.backend.arm.detect import detect_arch_version, getauxval cpuinfo = "Processor : ARMv%d-compatible processor rev 7 (v6l)""" cpuinfo2 = """processor : 0 @@ -29,6 +29,19 @@ address sizes : 36 bits physical, 48 bits virtual power management: """ +# From a Marvell Armada 370/XP +auxv = ( + '\x10\x00\x00\x00\xd7\xa8\x1e\x00\x06\x00\x00\x00\x00\x10\x00\x00\x11\x00' + '\x00\x00d\x00\x00\x00\x03\x00\x00\x004\x00\x01\x00\x04\x00\x00\x00 \x00' + '\x00\x00\x05\x00\x00\x00\t\x00\x00\x00\x07\x00\x00\x00\x00\xe0\xf3\xb6' + '\x08\x00\x00\x00\x00\x00\x00\x00\t\x00\x00\x00t\xcf\x04\x00\x0b\x00\x00' + '\x000\x0c\x00\x00\x0c\x00\x00\x000\x0c\x00\x00\r\x00\x00\x000\x0c\x00\x00' + '\x0e\x00\x00\x000\x0c\x00\x00\x17\x00\x00\x00\x00\x00\x00\x00\x19\x00\x00' + '\x00\x8a\xf3\x87\xbe\x1a\x00\x00\x00\x00\x00\x00\x00\x1f\x00\x00\x00\xec' + '\xff\x87\xbe\x0f\x00\x00\x00\x9a\xf3\x87\xbe\x00\x00\x00\x00\x00\x00\x00' + '\x00' +) + def write_cpuinfo(info): filepath = udir.join('get_arch_version') @@ -46,3 +59,10 @@ py.test.raises(ValueError, 'detect_arch_version(write_cpuinfo(cpuinfo % 5))') assert detect_arch_version(write_cpuinfo(cpuinfo2)) == 6 + + +def test_getauxval_no_neon(): + path = udir.join('auxv') + path.write(auxv, 'wb') + AT_HWCAP = 16 + assert getauxval(AT_HWCAP, filename=str(path)) == 2009303 diff --git a/rpython/jit/backend/detect_cpu.py b/rpython/jit/backend/detect_cpu.py --- a/rpython/jit/backend/detect_cpu.py +++ b/rpython/jit/backend/detect_cpu.py @@ -146,7 +146,7 @@ MODEL_X86_64: ['floats', 'singlefloats'], MODEL_X86_64_SSE4: ['floats', 'singlefloats'], MODEL_ARM: ['floats', 'singlefloats', 'longlong'], - MODEL_PPC_64: [], # we don't even have PPC directory, so no + MODEL_PPC_64: ['floats'], MODEL_S390_64: ['floats'], }[backend_name] diff --git a/rpython/jit/backend/llgraph/runner.py b/rpython/jit/backend/llgraph/runner.py --- a/rpython/jit/backend/llgraph/runner.py +++ b/rpython/jit/backend/llgraph/runner.py @@ -455,7 +455,7 @@ if box is not frame.current_op: value = frame.env[box] else: - value = box.getvalue() # 0 or 0.0 or NULL + value = 0 # box.getvalue() # 0 or 0.0 or NULL else: value = None values.append(value) @@ -472,6 +472,13 @@ # ------------------------------------------------------------ + def setup_descrs(self): + all_descrs = [] + for k, v in self.descrs.iteritems(): + v.descr_index = len(all_descrs) + all_descrs.append(v) + return all_descrs + def calldescrof(self, FUNC, ARGS, RESULT, effect_info): key = ('call', getkind(RESULT), tuple([getkind(A) for A in ARGS]), 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 @@ -216,9 +216,6 @@ gcroot_markers = None - frame_positions = None - frame_assignments = None - def __init__(self, translated=None): if translated is None: translated = we_are_translated() @@ -323,12 +320,6 @@ assert gcrootmap is not None for pos, mark in self.gcroot_markers: gcrootmap.register_asm_addr(rawstart + pos, mark) - if cpu.HAS_CODEMAP: - cpu.codemap.register_frame_depth_map(rawstart, rawstart + size, - self.frame_positions, - self.frame_assignments) - self.frame_positions = None - self.frame_assignments = None return rawstart def _become_a_plain_block_builder(self): diff --git a/rpython/jit/backend/llsupport/assembler.py b/rpython/jit/backend/llsupport/assembler.py --- a/rpython/jit/backend/llsupport/assembler.py +++ b/rpython/jit/backend/llsupport/assembler.py @@ -23,10 +23,11 @@ class GuardToken(object): def __init__(self, cpu, gcmap, faildescr, failargs, fail_locs, - guard_opnum, frame_depth): + guard_opnum, frame_depth, faildescrindex): assert isinstance(faildescr, AbstractFailDescr) self.cpu = cpu self.faildescr = faildescr + self.faildescrindex = faildescrindex self.failargs = failargs self.fail_locs = fail_locs self.gcmap = self.compute_gcmap(gcmap, failargs, @@ -144,6 +145,22 @@ self.codemap_builder = CodemapBuilder() self._finish_gcmap = lltype.nullptr(jitframe.GCMAP) + def setup_gcrefs_list(self, allgcrefs): + self._allgcrefs = allgcrefs + self._allgcrefs_faildescr_next = 0 + + def teardown_gcrefs_list(self): + self._allgcrefs = None + + def get_gcref_from_faildescr(self, descr): + """This assumes that it is called in order for all faildescrs.""" + search = cast_instance_to_gcref(descr) + while not _safe_eq( + self._allgcrefs[self._allgcrefs_faildescr_next], search): + self._allgcrefs_faildescr_next += 1 + assert self._allgcrefs_faildescr_next < len(self._allgcrefs) + return self._allgcrefs_faildescr_next + def set_debug(self, v): r = self._debug self._debug = v @@ -186,8 +203,7 @@ break exc = guardtok.must_save_exception() target = self.failure_recovery_code[exc + 2 * withfloats] - fail_descr = cast_instance_to_gcref(guardtok.faildescr) - fail_descr = rffi.cast(lltype.Signed, fail_descr) + faildescrindex = guardtok.faildescrindex base_ofs = self.cpu.get_baseofs_of_frame_field() # # in practice, about 2/3rd of 'positions' lists that we build are @@ -229,7 +245,7 @@ self._previous_rd_locs = positions # write down the positions of locs guardtok.faildescr.rd_locs = positions - return fail_descr, target + return faildescrindex, target def enter_portal_frame(self, op): if self.cpu.HAS_CODEMAP: @@ -288,7 +304,7 @@ gcref = cast_instance_to_gcref(value) if gcref: - rgc._make_sure_does_not_move(gcref) + rgc._make_sure_does_not_move(gcref) # but should be prebuilt value = rffi.cast(lltype.Signed, gcref) je_location = self._call_assembler_check_descr(value, tmploc) # @@ -331,7 +347,7 @@ counter = self._register_counter(tp, number, token) c_adr = ConstInt(rffi.cast(lltype.Signed, counter)) operations.append( - ResOperation(rop.INCREMENT_DEBUG_COUNTER, [c_adr], None)) + ResOperation(rop.INCREMENT_DEBUG_COUNTER, [c_adr])) def _register_counter(self, tp, number, token): # YYY very minor leak -- we need the counters to stay alive @@ -451,3 +467,8 @@ r_uint(rawstart + codeendpos))) debug_stop("jit-backend-addr") +def _safe_eq(x, y): + try: + return x == y + except AttributeError: # minor mess + return False diff --git a/rpython/jit/backend/llsupport/codemap.py b/rpython/jit/backend/llsupport/codemap.py --- a/rpython/jit/backend/llsupport/codemap.py +++ b/rpython/jit/backend/llsupport/codemap.py @@ -41,10 +41,6 @@ RPY_EXTERN long pypy_yield_codemap_at_addr(void *codemap_raw, long addr, long *current_pos_addr); -RPY_EXTERN long pypy_jit_depthmap_add(unsigned long addr, unsigned int size, - unsigned int stackdepth); -RPY_EXTERN void pypy_jit_depthmap_clear(unsigned long addr, unsigned int size); - """], separate_module_sources=[ open(os.path.join(srcdir, 'skiplist.c'), 'r').read() + open(os.path.join(srcdir, 'codemap.c'), 'r').read() @@ -64,15 +60,6 @@ pypy_jit_codemap_firstkey = llexternal('pypy_jit_codemap_firstkey', [], lltype.Signed) -pypy_jit_depthmap_add = llexternal('pypy_jit_depthmap_add', - [lltype.Signed, lltype.Signed, - lltype.Signed], lltype.Signed) -pypy_jit_depthmap_clear = llexternal('pypy_jit_depthmap_clear', - [lltype.Signed, lltype.Signed], - lltype.Void) - -stack_depth_at_loc = llexternal('pypy_jit_stack_depth_at_loc', - [lltype.Signed], lltype.Signed) find_codemap_at_addr = llexternal('pypy_find_codemap_at_addr', [lltype.Signed, rffi.CArrayPtr(lltype.Signed)], llmemory.Address) @@ -102,20 +89,6 @@ items = pypy_jit_codemap_del(start, stop - start) if items: lltype.free(items, flavor='raw', track_allocation=False) - pypy_jit_depthmap_clear(start, stop - start) - _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit