Author: mattip <[email protected]>
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)
[email protected]("os.name != 'posix' or 'darwin' in sys.platform")
[email protected]("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
[email protected]("os.name != 'posix' or 'darwin' in sys.platform")
+
[email protected]("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
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit