Author: Carl Friedrich Bolz <[email protected]>
Branch: typed-cells
Changeset: r75650:2ac6556197f9
Date: 2015-02-02 16:30 +0100
http://bitbucket.org/pypy/pypy/changeset/2ac6556197f9/
Log: merge default
diff --git a/lib-python/2.7/ctypes/test/test_frombuffer.py
b/lib-python/2.7/ctypes/test/test_frombuffer.py
--- a/lib-python/2.7/ctypes/test/test_frombuffer.py
+++ b/lib-python/2.7/ctypes/test/test_frombuffer.py
@@ -2,7 +2,6 @@
import array
import gc
import unittest
-from ctypes.test import xfail
class X(Structure):
_fields_ = [("c_int", c_int)]
@@ -11,7 +10,6 @@
self._init_called = True
class Test(unittest.TestCase):
- @xfail
def test_fom_buffer(self):
a = array.array("i", range(16))
x = (c_int * 16).from_buffer(a)
@@ -34,10 +32,9 @@
del a; gc.collect(); gc.collect(); gc.collect()
self.assertEqual(x[:], expected)
- self.assertRaises(TypeError,
+ self.assertRaises((TypeError, ValueError),
(c_char * 16).from_buffer, "a" * 16)
- @xfail
def test_fom_buffer_with_offset(self):
a = array.array("i", range(16))
x = (c_int * 15).from_buffer(a, sizeof(c_int))
@@ -46,7 +43,6 @@
self.assertRaises(ValueError, lambda: (c_int * 16).from_buffer(a,
sizeof(c_int)))
self.assertRaises(ValueError, lambda: (c_int * 1).from_buffer(a, 16 *
sizeof(c_int)))
- @xfail
def test_from_buffer_copy(self):
a = array.array("i", range(16))
x = (c_int * 16).from_buffer_copy(a)
@@ -71,7 +67,6 @@
x = (c_char * 16).from_buffer_copy("a" * 16)
self.assertEqual(x[:], "a" * 16)
- @xfail
def test_fom_buffer_copy_with_offset(self):
a = array.array("i", range(16))
x = (c_int * 15).from_buffer_copy(a, sizeof(c_int))
diff --git a/lib_pypy/_ctypes/basics.py b/lib_pypy/_ctypes/basics.py
--- a/lib_pypy/_ctypes/basics.py
+++ b/lib_pypy/_ctypes/basics.py
@@ -83,6 +83,37 @@
def in_dll(self, dll, name):
return self.from_address(dll._handle.getaddressindll(name))
+ def from_buffer(self, obj, offset=0):
+ size = self._sizeofinstances()
+ buf = buffer(obj, offset, size)
+ if len(buf) < size:
+ raise ValueError(
+ "Buffer size too small (%d instead of at least %d bytes)"
+ % (len(buf) + offset, size + offset))
+ raw_addr = buf._pypy_raw_address()
+ result = self.from_address(raw_addr)
+ result._ensure_objects()['ffffffff'] = obj
+ return result
+
+ def from_buffer_copy(self, obj, offset=0):
+ size = self._sizeofinstances()
+ buf = buffer(obj, offset, size)
+ if len(buf) < size:
+ raise ValueError(
+ "Buffer size too small (%d instead of at least %d bytes)"
+ % (len(buf) + offset, size + offset))
+ result = self()
+ dest = result._buffer.buffer
+ try:
+ raw_addr = buf._pypy_raw_address()
+ except ValueError:
+ _rawffi.rawstring2charp(dest, buf)
+ else:
+ from ctypes import memmove
+ memmove(dest, raw_addr, size)
+ return result
+
+
class CArgObject(object):
""" simple wrapper around buffer, just for the case of freeing
it afterwards
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
@@ -1,3 +1,4 @@
+import sys
import _rawffi
from _ctypes.basics import _CData, _CDataMeta, keepalive_key,\
store_reference, ensure_objects, CArgObject
@@ -178,6 +179,8 @@
instance = StructOrUnion.__new__(self)
if isinstance(address, _rawffi.StructureInstance):
address = address.buffer
+ # fix the address: turn it into as unsigned, in case it is negative
+ address = address & (sys.maxint * 2 + 1)
instance.__dict__['_buffer'] = self._ffistruct.fromaddress(address)
return instance
diff --git a/pypy/doc/faq.rst b/pypy/doc/faq.rst
--- a/pypy/doc/faq.rst
+++ b/pypy/doc/faq.rst
@@ -3,6 +3,13 @@
.. contents::
+See also: `Frequently ask questions about RPython.`__
+
+.. __: http://rpython.readthedocs.org/en/latest/faq.html
+
+---------------------------
+
+
What is PyPy?
-------------
diff --git a/pypy/doc/project-ideas.rst b/pypy/doc/project-ideas.rst
--- a/pypy/doc/project-ideas.rst
+++ b/pypy/doc/project-ideas.rst
@@ -1,14 +1,23 @@
Potential project list
======================
-===========================
-Simple tasks for newcomers:
-===========================
+==========================
+Simple tasks for newcomers
+==========================
-Optimize random
----------------
+* Tkinter module missing support for threads:
+
https://bitbucket.org/pypy/pypy/issue/1929/tkinter-broken-for-threaded-python-on-both
-https://bitbucket.org/pypy/pypy/issue/1901/try-using-a-different-implementation-of
+* Optimize random:
+
https://bitbucket.org/pypy/pypy/issue/1901/try-using-a-different-implementation-of
+
+* Implement AF_XXX packet types of sockets:
+ https://bitbucket.org/pypy/pypy/issue/1942/support-for-af_xxx-sockets
+
+
+==================
+Mid-to-large tasks
+==================
Below is a list of projects that are interesting for potential contributors
who are seriously interested in the PyPy project. They mostly share common
@@ -33,15 +42,8 @@
------------------------
PyPy's bytearray type is very inefficient. It would be an interesting
-task to look into possible optimizations on this.
-
-Implement AF_XXX packet types for PyPy
---------------------------------------
-
-PyPy is missing AF_XXX types of sockets. Implementing it is easy-to-medium
-task. `bug report`_
-
-.. _`bug report`:
https://bitbucket.org/pypy/pypy/issue/1942/support-for-af_xxx-sockets#more
+task to look into possible optimizations on this. (XXX current status
+unknown; ask on #pypy for updates on this.)
Implement copy-on-write list slicing
------------------------------------
@@ -106,6 +108,8 @@
Translation Toolchain
---------------------
+(XXX this is unlikely to be feasible.)
+
* Incremental or distributed translation.
* Allow separate compilation of extension modules.
diff --git a/pypy/interpreter/pyframe.py b/pypy/interpreter/pyframe.py
--- a/pypy/interpreter/pyframe.py
+++ b/pypy/interpreter/pyframe.py
@@ -439,7 +439,10 @@
f_back = space.interp_w(PyFrame, w_f_back, can_be_None=True)
new_frame.f_backref = jit.non_virtual_ref(f_back)
- new_frame.builtin = space.interp_w(Module, w_builtin)
+ if space.config.objspace.honor__builtins__:
+ new_frame.builtin = space.interp_w(Module, w_builtin)
+ else:
+ assert space.interp_w(Module, w_builtin) is space.builtin
new_frame.set_blocklist([unpickle_block(space, w_blk)
for w_blk in
space.unpackiterable(w_blockstack)])
values_w = maker.slp_from_tuple_with_nulls(space, w_valuestack)
@@ -524,9 +527,10 @@
# cellvars are values exported to inner scopes
# freevars are values coming from outer scopes
- freevarnames = list(self.pycode.co_cellvars)
+ # (see locals2fast for why CO_OPTIMIZED)
+ freevarnames = self.pycode.co_cellvars
if self.pycode.co_flags & consts.CO_OPTIMIZED:
- freevarnames.extend(self.pycode.co_freevars)
+ freevarnames = freevarnames + self.pycode.co_freevars
for i in range(len(freevarnames)):
name = freevarnames[i]
cell = self.cells[i]
@@ -555,7 +559,16 @@
self.setfastscope(new_fastlocals_w)
- freevarnames = self.pycode.co_cellvars + self.pycode.co_freevars
+ freevarnames = self.pycode.co_cellvars
+ if self.pycode.co_flags & consts.CO_OPTIMIZED:
+ freevarnames = freevarnames + self.pycode.co_freevars
+ # If the namespace is unoptimized, then one of the
+ # following cases applies:
+ # 1. It does not contain free variables, because it
+ # uses import * or is a top-level namespace.
+ # 2. It is a class namespace.
+ # We don't want to accidentally copy free variables
+ # into the locals dict used by the class.
for i in range(len(freevarnames)):
name = freevarnames[i]
cell = self.cells[i]
diff --git a/pypy/interpreter/test/test_pyframe.py
b/pypy/interpreter/test/test_pyframe.py
--- a/pypy/interpreter/test/test_pyframe.py
+++ b/pypy/interpreter/test/test_pyframe.py
@@ -516,3 +516,21 @@
assert seen == [(1, f, firstline + 6, 'line', None),
(1, f, firstline + 7, 'line', None),
(1, f, firstline + 8, 'line', None)]
+
+ def test_locals2fast_freevar_bug(self):
+ import sys
+ def f(n):
+ class A(object):
+ def g(self):
+ return n
+ n = 42
+ return A()
+ res = f(10).g()
+ assert res == 10
+ #
+ def trace(*args):
+ return trace
+ sys.settrace(trace)
+ res = f(10).g()
+ sys.settrace(None)
+ assert res == 10
diff --git a/rpython/doc/faq.rst b/rpython/doc/faq.rst
--- a/rpython/doc/faq.rst
+++ b/rpython/doc/faq.rst
@@ -3,6 +3,12 @@
.. contents::
+See also: `Frequently ask questions about PyPy.`__
+
+.. __: http://pypy.readthedocs.org/en/latest/faq.html
+
+--------------------------
+
What is RPython?
----------------
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
@@ -1298,5 +1298,6 @@
self.load_reg(self.mc, res_loc, r.sp, ofs)
scale = get_scale(size_loc.value)
signed = (sign_loc.value != 0)
- self._load_from_mem(res_loc, res_loc, ofs_loc, scale, signed, fcond)
+ self._load_from_mem(res_loc, res_loc, ofs_loc, imm(scale), signed,
+ fcond)
return fcond
diff --git a/rpython/jit/backend/x86/valgrind.py
b/rpython/jit/backend/x86/valgrind.py
--- a/rpython/jit/backend/x86/valgrind.py
+++ b/rpython/jit/backend/x86/valgrind.py
@@ -6,6 +6,7 @@
from rpython.rtyper.lltypesystem import lltype, llmemory, rffi
from rpython.translator.tool.cbuild import ExternalCompilationInfo
from rpython.rlib.objectmodel import we_are_translated
+from rpython.jit.backend.x86.arch import WORD
eci = ExternalCompilationInfo(includes = ['valgrind/valgrind.h'])
@@ -13,9 +14,91 @@
try:
rffi_platform.verify_eci(eci)
except rffi_platform.CompilationError:
- VALGRIND_DISCARD_TRANSLATIONS = None
-else:
- VALGRIND_DISCARD_TRANSLATIONS = rffi.llexternal(
+ # Can't open 'valgrind/valgrind.h'. It is a bad idea to just go
+ # ahead and not compile the valgrind-specific hacks. Instead,
+ # we'll include manually the few needed macros from a hopefully
+ # standard valgrind.h file.
+ eci = ExternalCompilationInfo(post_include_bits = [r"""
+/************ Valgrind support: only with GCC/clang for now ***********/
+/** This code is inserted only if valgrind/valgrind.h is not found **/
+/**********************************************************************/
+#ifdef __GNUC__
+
+#if ${WORD} == 4 /* if 32-bit x86 */
+
+#define VG__SPECIAL_INSTRUCTION_PREAMBLE \
+ "roll $3, %%edi ; roll $13, %%edi\n\t" \
+ "roll $29, %%edi ; roll $19, %%edi\n\t"
+#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
+ _zzq_default, _zzq_request, \
+ _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
+ __extension__ \
+ ({volatile unsigned int _zzq_args[6]; \
+ volatile unsigned int _zzq_result; \
+ _zzq_args[0] = (unsigned int)(_zzq_request); \
+ _zzq_args[1] = (unsigned int)(_zzq_arg1); \
+ _zzq_args[2] = (unsigned int)(_zzq_arg2); \
+ _zzq_args[3] = (unsigned int)(_zzq_arg3); \
+ _zzq_args[4] = (unsigned int)(_zzq_arg4); \
+ _zzq_args[5] = (unsigned int)(_zzq_arg5); \
+ __asm__ volatile(VG__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %EDX = client_request ( %EAX ) */ \
+ "xchgl %%ebx,%%ebx" \
+ : "=d" (_zzq_result) \
+ : "a" (&_zzq_args[0]), "0" (_zzq_default) \
+ : "cc", "memory" \
+ ); \
+ _zzq_result; \
+ })
+
+#else /* 64-bit x86-64 */
+
+#define VG__SPECIAL_INSTRUCTION_PREAMBLE \
+ "rolq $3, %%rdi ; rolq $13, %%rdi\n\t" \
+ "rolq $61, %%rdi ; rolq $51, %%rdi\n\t"
+#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
+ _zzq_default, _zzq_request, \
+ _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
+ __extension__ \
+ ({ volatile unsigned long long int _zzq_args[6]; \
+ volatile unsigned long long int _zzq_result; \
+ _zzq_args[0] = (unsigned long long int)(_zzq_request); \
+ _zzq_args[1] = (unsigned long long int)(_zzq_arg1); \
+ _zzq_args[2] = (unsigned long long int)(_zzq_arg2); \
+ _zzq_args[3] = (unsigned long long int)(_zzq_arg3); \
+ _zzq_args[4] = (unsigned long long int)(_zzq_arg4); \
+ _zzq_args[5] = (unsigned long long int)(_zzq_arg5); \
+ __asm__ volatile(VG__SPECIAL_INSTRUCTION_PREAMBLE \
+ /* %RDX = client_request ( %RAX ) */ \
+ "xchgq %%rbx,%%rbx" \
+ : "=d" (_zzq_result) \
+ : "a" (&_zzq_args[0]), "0" (_zzq_default) \
+ : "cc", "memory" \
+ ); \
+ _zzq_result; \
+ })
+#endif
+
+#define VALGRIND_DO_CLIENT_REQUEST_STMT(_zzq_request, _zzq_arg1, \
+ _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
+ do { (void) VALGRIND_DO_CLIENT_REQUEST_EXPR(0, \
+ (_zzq_request), (_zzq_arg1), (_zzq_arg2), \
+ (_zzq_arg3), (_zzq_arg4), (_zzq_arg5)); } while (0)
+
+#define VG_USERREQ__DISCARD_TRANSLATIONS 0x1002
+#define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) \
+ VALGRIND_DO_CLIENT_REQUEST_STMT(VG_USERREQ__DISCARD_TRANSLATIONS, \
+ _qzz_addr, _qzz_len, 0, 0, 0)
+
+/**********************************************************************/
+#else /* if !__GNUC__ */
+#define VALGRIND_DISCARD_TRANSLATIONS(_qzz_addr,_qzz_len) do { } while(0)
+#endif
+/**********************************************************************/
+""".replace("${WORD}", str(WORD))])
+
+
+VALGRIND_DISCARD_TRANSLATIONS = rffi.llexternal(
"VALGRIND_DISCARD_TRANSLATIONS",
[llmemory.Address, lltype.Signed],
lltype.Void,
@@ -26,5 +109,5 @@
# ____________________________________________________________
def discard_translations(data, size):
- if we_are_translated() and VALGRIND_DISCARD_TRANSLATIONS is not None:
+ if we_are_translated():
VALGRIND_DISCARD_TRANSLATIONS(llmemory.cast_int_to_adr(data), size)
diff --git a/rpython/rlib/rfile.py b/rpython/rlib/rfile.py
--- a/rpython/rlib/rfile.py
+++ b/rpython/rlib/rfile.py
@@ -477,8 +477,7 @@
@enforceargs(None, str)
def write(self, value):
self._check_closed()
- ll_value, is_pinned, is_raw = rffi.get_nonmovingbuffer(value)
- try:
+ with rffi.scoped_nonmovingbuffer(value) as ll_value:
# note that since we got a nonmoving buffer, it is either raw
# or already cannot move, so the arithmetics below are fine
length = len(value)
@@ -487,8 +486,6 @@
errno = rposix.get_saved_errno()
c_clearerr(self._ll_file)
raise IOError(errno, os.strerror(errno))
- finally:
- rffi.free_nonmovingbuffer(value, ll_value, is_pinned, is_raw)
def flush(self):
self._check_closed()
diff --git a/rpython/rlib/rgc.py b/rpython/rlib/rgc.py
--- a/rpython/rlib/rgc.py
+++ b/rpython/rlib/rgc.py
@@ -684,7 +684,7 @@
class RegisterGcTraceEntry(ExtRegistryEntry):
_about_ = register_custom_trace_hook
- def compute_result_annotation(self, *args_s):
+ def compute_result_annotation(self, s_tp, s_lambda_func):
pass
def specialize_call(self, hop):
@@ -692,3 +692,26 @@
lambda_func = hop.args_s[1].const
hop.exception_cannot_occur()
hop.rtyper.custom_trace_funcs.append((TP, lambda_func()))
+
+def register_custom_light_finalizer(TP, lambda_func):
+ """ This function does not do anything, but called from any annotated
+ place, will tell that "func" is used as a lightweight finalizer for TP.
+ The func must be specified as "lambda: func" in this call, for internal
+ reasons.
+ """
+
+class RegisterCustomLightFinalizer(ExtRegistryEntry):
+ _about_ = register_custom_light_finalizer
+
+ def compute_result_annotation(self, s_tp, s_lambda_func):
+ pass
+
+ def specialize_call(self, hop):
+ from rpython.rtyper.llannotation import SomePtr
+ TP = hop.args_s[0].const
+ lambda_func = hop.args_s[1].const
+ ll_func = lambda_func()
+ args_s = [SomePtr(lltype.Ptr(TP))]
+ funcptr = hop.rtyper.annotate_helper_fn(ll_func, args_s)
+ hop.exception_cannot_occur()
+ lltype.attachRuntimeTypeInfo(TP, destrptr=funcptr)
diff --git a/rpython/translator/c/src/asm_msvc.h
b/rpython/translator/c/src/asm_msvc.h
--- a/rpython/translator/c/src/asm_msvc.h
+++ b/rpython/translator/c/src/asm_msvc.h
@@ -2,3 +2,14 @@
#define PYPY_X86_CHECK_SSE2_DEFINED
RPY_EXTERN void pypy_x86_check_sse2(void);
#endif
+
+
+/* Provides the same access to RDTSC as used by the JIT backend. This
+ is needed (at least if the JIT is enabled) because otherwise the
+ JIT-produced assembler would use RDTSC while the non-jitted code
+ would use QueryPerformanceCounter(), giving different incompatible
+ results. See issue #900.
+*/
+#include <intrin.h>
+#pragma intrinsic(__rdtsc)
+#define READ_TIMESTAMP(val) do { val = (long long)__rdtsc(); } while (0)
diff --git a/rpython/translator/c/test/test_newgc.py
b/rpython/translator/c/test/test_newgc.py
--- a/rpython/translator/c/test/test_newgc.py
+++ b/rpython/translator/c/test/test_newgc.py
@@ -473,6 +473,31 @@
res = self.run('custom_trace', 0)
assert res == 10000
+ def define_custom_light_finalizer(cls):
+ from rpython.rtyper.annlowlevel import llhelper
+ #
+ T = lltype.Struct('T', ('count', lltype.Signed))
+ t = lltype.malloc(T, zero=True, immortal=True, flavor='raw')
+ #
+ S = lltype.GcStruct('S', rtti=True)
+ def customlightfinlz(addr):
+ t.count += 1
+ lambda_customlightfinlz = lambda: customlightfinlz
+ #
+ def setup():
+ rgc.register_custom_light_finalizer(S, lambda_customlightfinlz)
+ for i in range(10000):
+ lltype.malloc(S)
+ def f(n):
+ setup()
+ llop.gc__collect(lltype.Void)
+ return t.count
+ return f
+
+ def test_custom_light_finalizer(self):
+ res = self.run('custom_light_finalizer', 0)
+ assert res == 10000
+
def define_weakref(cls):
import weakref
diff --git a/rpython/translator/tool/cbuild.py
b/rpython/translator/tool/cbuild.py
--- a/rpython/translator/tool/cbuild.py
+++ b/rpython/translator/tool/cbuild.py
@@ -59,7 +59,11 @@
separately and linked later on. (If an .h file is needed for
other .c files to access this, it can be put in includes.)
- (export_symbols: killed, replaced by @rlib.entrypoint.export_symbol)
+ (export_symbols: killed; you need, depending on the case, to
+ add the RPY_EXTERN or RPY_EXPORTED macro just before the
+ declaration of each function in the C header file, as explained
+ in translator/c/src/precommondefs.h; or you need the decorator
+ @rlib.entrypoint.export_symbol)
compile_extra: list of parameters which will be directly passed to
the compiler
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit