[pypy-commit] pypy sepcomp2: hg merge default
amauryfa
noreply at buildbot.pypy.org
Wed Feb 22 23:24:35 CET 2012
Author: Amaury Forgeot d'Arc <amauryfa at gmail.com>
Branch: sepcomp2
Changeset: r52777:3ac122eefc54
Date: 2012-02-22 23:23 +0100
http://bitbucket.org/pypy/pypy/changeset/3ac122eefc54/
Log: hg merge default
diff --git a/lib_pypy/_ctypes/array.py b/lib_pypy/_ctypes/array.py
--- a/lib_pypy/_ctypes/array.py
+++ b/lib_pypy/_ctypes/array.py
@@ -1,9 +1,9 @@
-
+import _ffi
import _rawffi
from _ctypes.basics import _CData, cdata_from_address, _CDataMeta, sizeof
from _ctypes.basics import keepalive_key, store_reference, ensure_objects
-from _ctypes.basics import CArgObject
+from _ctypes.basics import CArgObject, as_ffi_pointer
class ArrayMeta(_CDataMeta):
def __new__(self, name, cls, typedict):
@@ -211,6 +211,9 @@
def _to_ffi_param(self):
return self._get_buffer_value()
+ def _as_ffi_pointer_(self, ffitype):
+ return as_ffi_pointer(self, ffitype)
+
ARRAY_CACHE = {}
def create_array_type(base, length):
@@ -228,5 +231,6 @@
_type_ = base
)
cls = ArrayMeta(name, (Array,), tpdict)
+ cls._ffiargtype = _ffi.types.Pointer(base.get_ffi_argtype())
ARRAY_CACHE[key] = cls
return cls
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
@@ -230,5 +230,16 @@
}
+# called from primitive.py, pointer.py, array.py
+def as_ffi_pointer(value, ffitype):
+ my_ffitype = type(value).get_ffi_argtype()
+ # for now, we always allow types.pointer, else a lot of tests
+ # break. We need to rethink how pointers are represented, though
+ if my_ffitype is not ffitype and ffitype is not _ffi.types.void_p:
+ raise ArgumentError("expected %s instance, got %s" % (type(value),
+ ffitype))
+ return value._get_buffer_value()
+
+
# used by "byref"
from _ctypes.pointer import pointer
diff --git a/lib_pypy/_ctypes/pointer.py b/lib_pypy/_ctypes/pointer.py
--- a/lib_pypy/_ctypes/pointer.py
+++ b/lib_pypy/_ctypes/pointer.py
@@ -3,7 +3,7 @@
import _ffi
from _ctypes.basics import _CData, _CDataMeta, cdata_from_address, ArgumentError
from _ctypes.basics import keepalive_key, store_reference, ensure_objects
-from _ctypes.basics import sizeof, byref
+from _ctypes.basics import sizeof, byref, as_ffi_pointer
from _ctypes.array import Array, array_get_slice_params, array_slice_getitem,\
array_slice_setitem
@@ -119,14 +119,6 @@
def _as_ffi_pointer_(self, ffitype):
return as_ffi_pointer(self, ffitype)
-def as_ffi_pointer(value, ffitype):
- my_ffitype = type(value).get_ffi_argtype()
- # for now, we always allow types.pointer, else a lot of tests
- # break. We need to rethink how pointers are represented, though
- if my_ffitype is not ffitype and ffitype is not _ffi.types.void_p:
- raise ArgumentError("expected %s instance, got %s" % (type(value),
- ffitype))
- return value._get_buffer_value()
def _cast_addr(obj, _, tp):
if not (isinstance(tp, _CDataMeta) and tp._is_pointer_like()):
diff --git a/pypy/doc/cpython_differences.rst b/pypy/doc/cpython_differences.rst
--- a/pypy/doc/cpython_differences.rst
+++ b/pypy/doc/cpython_differences.rst
@@ -313,5 +313,10 @@
implementation detail that shows up because of internal C-level slots
that PyPy does not have.
+* the ``__dict__`` attribute of new-style classes returns a normal dict, as
+ opposed to a dict proxy like in CPython. Mutating the dict will change the
+ type and vice versa. For builtin types, a dictionary will be returned that
+ cannot be changed (but still looks and behaves like a normal dictionary).
+
.. include:: _ref.txt
diff --git a/pypy/jit/backend/llsupport/gc.py b/pypy/jit/backend/llsupport/gc.py
--- a/pypy/jit/backend/llsupport/gc.py
+++ b/pypy/jit/backend/llsupport/gc.py
@@ -1,7 +1,6 @@
import os
from pypy.rlib import rgc
from pypy.rlib.objectmodel import we_are_translated, specialize
-from pypy.rlib.debug import fatalerror
from pypy.rlib.rarithmetic import ovfcheck
from pypy.rpython.lltypesystem import lltype, llmemory, rffi, rclass, rstr
from pypy.rpython.lltypesystem import llgroup
diff --git a/pypy/jit/backend/x86/assembler.py b/pypy/jit/backend/x86/assembler.py
--- a/pypy/jit/backend/x86/assembler.py
+++ b/pypy/jit/backend/x86/assembler.py
@@ -33,7 +33,7 @@
from pypy.jit.backend.x86.support import values_array
from pypy.jit.backend.x86 import support
from pypy.rlib.debug import (debug_print, debug_start, debug_stop,
- have_debug_prints)
+ have_debug_prints, fatalerror_notb)
from pypy.rlib import rgc
from pypy.rlib.clibffi import FFI_DEFAULT_ABI
from pypy.jit.backend.x86.jump import remap_frame_layout
@@ -104,6 +104,7 @@
self._debug = v
def setup_once(self):
+ self._check_sse2()
# the address of the function called by 'new'
gc_ll_descr = self.cpu.gc_ll_descr
gc_ll_descr.initialize()
@@ -161,6 +162,28 @@
debug_print(prefix + ':' + str(struct.i))
debug_stop('jit-backend-counts')
+ _CHECK_SSE2_FUNC_PTR = lltype.Ptr(lltype.FuncType([], lltype.Signed))
+
+ def _check_sse2(self):
+ if WORD == 8:
+ return # all x86-64 CPUs support SSE2
+ if not self.cpu.supports_floats:
+ return # the CPU doesn't support float, so we don't need SSE2
+ #
+ from pypy.jit.backend.x86.detect_sse2 import INSNS
+ mc = codebuf.MachineCodeBlockWrapper()
+ for c in INSNS:
+ mc.writechar(c)
+ rawstart = mc.materialize(self.cpu.asmmemmgr, [])
+ fnptr = rffi.cast(self._CHECK_SSE2_FUNC_PTR, rawstart)
+ features = fnptr()
+ if bool(features & (1<<25)) and bool(features & (1<<26)):
+ return # CPU supports SSE2
+ fatalerror_notb(
+ "This version of PyPy was compiled for a x86 CPU supporting SSE2.\n"
+ "Your CPU is too old. Please translate a PyPy with the option:\n"
+ "--jit-backend=x86-without-sse2")
+
def _build_float_constants(self):
datablockwrapper = MachineDataBlockWrapper(self.cpu.asmmemmgr, [])
float_constants = datablockwrapper.malloc_aligned(32, alignment=16)
diff --git a/pypy/jit/backend/x86/detect_sse2.py b/pypy/jit/backend/x86/detect_sse2.py
--- a/pypy/jit/backend/x86/detect_sse2.py
+++ b/pypy/jit/backend/x86/detect_sse2.py
@@ -1,17 +1,18 @@
import autopath
-from pypy.rpython.lltypesystem import lltype, rffi
-from pypy.rlib.rmmap import alloc, free
+INSNS = ("\xB8\x01\x00\x00\x00" # MOV EAX, 1
+ "\x53" # PUSH EBX
+ "\x0F\xA2" # CPUID
+ "\x5B" # POP EBX
+ "\x92" # XCHG EAX, EDX
+ "\xC3") # RET
def detect_sse2():
+ from pypy.rpython.lltypesystem import lltype, rffi
+ from pypy.rlib.rmmap import alloc, free
data = alloc(4096)
pos = 0
- for c in ("\xB8\x01\x00\x00\x00" # MOV EAX, 1
- "\x53" # PUSH EBX
- "\x0F\xA2" # CPUID
- "\x5B" # POP EBX
- "\x92" # XCHG EAX, EDX
- "\xC3"): # RET
+ for c in INSNS:
data[pos] = c
pos += 1
fnptr = rffi.cast(lltype.Ptr(lltype.FuncType([], lltype.Signed)), data)
diff --git a/pypy/jit/metainterp/warmspot.py b/pypy/jit/metainterp/warmspot.py
--- a/pypy/jit/metainterp/warmspot.py
+++ b/pypy/jit/metainterp/warmspot.py
@@ -453,7 +453,7 @@
if sys.stdout == sys.__stdout__:
import pdb; pdb.post_mortem(tb)
raise e.__class__, e, tb
- fatalerror('~~~ Crash in JIT! %s' % (e,), traceback=True)
+ fatalerror('~~~ Crash in JIT! %s' % (e,))
crash_in_jit._dont_inline_ = True
if self.translator.rtyper.type_system.name == 'lltypesystem':
diff --git a/pypy/module/cpyext/stubs.py b/pypy/module/cpyext/stubs.py
--- a/pypy/module/cpyext/stubs.py
+++ b/pypy/module/cpyext/stubs.py
@@ -1293,28 +1293,6 @@
that haven't been explicitly destroyed at that point."""
raise NotImplementedError
- at cpython_api([rffi.VOIDP], lltype.Void)
-def Py_AddPendingCall(space, func):
- """Post a notification to the Python main thread. If successful, func will
- be called with the argument arg at the earliest convenience. func will be
- called having the global interpreter lock held and can thus use the full
- Python API and can take any action such as setting object attributes to
- signal IO completion. It must return 0 on success, or -1 signalling an
- exception. The notification function won't be interrupted to perform another
- asynchronous notification recursively, but it can still be interrupted to
- switch threads if the global interpreter lock is released, for example, if it
- calls back into Python code.
-
- This function returns 0 on success in which case the notification has been
- scheduled. Otherwise, for example if the notification buffer is full, it
- returns -1 without setting any exception.
-
- This function can be called on any thread, be it a Python thread or some
- other system thread. If it is a Python thread, it doesn't matter if it holds
- the global interpreter lock or not.
- """
- raise NotImplementedError
-
@cpython_api([Py_tracefunc, PyObject], lltype.Void)
def PyEval_SetProfile(space, func, obj):
"""Set the profiler function to func. The obj parameter is passed to the
@@ -2373,16 +2351,6 @@
properly supporting 64-bit systems."""
raise NotImplementedError
- at cpython_api([PyObject, PyObject, PyObject, Py_ssize_t], PyObject)
-def PyUnicode_Replace(space, str, substr, replstr, maxcount):
- """Replace at most maxcount occurrences of substr in str with replstr and
- return the resulting Unicode object. maxcount == -1 means replace all
- occurrences.
-
- This function used an int type for maxcount. This might
- require changes in your code for properly supporting 64-bit systems."""
- raise NotImplementedError
-
@cpython_api([PyObject, PyObject, rffi.INT_real], PyObject)
def PyUnicode_RichCompare(space, left, right, op):
"""Rich compare two unicode strings and return one of the following:
diff --git a/pypy/module/cpyext/stubsactive.py b/pypy/module/cpyext/stubsactive.py
--- a/pypy/module/cpyext/stubsactive.py
+++ b/pypy/module/cpyext/stubsactive.py
@@ -38,3 +38,31 @@
def Py_MakePendingCalls(space):
return 0
+pending_call = lltype.Ptr(lltype.FuncType([rffi.VOIDP], rffi.INT_real))
+ at cpython_api([pending_call, rffi.VOIDP], rffi.INT_real, error=-1)
+def Py_AddPendingCall(space, func, arg):
+ """Post a notification to the Python main thread. If successful,
+ func will be called with the argument arg at the earliest
+ convenience. func will be called having the global interpreter
+ lock held and can thus use the full Python API and can take any
+ action such as setting object attributes to signal IO completion.
+ It must return 0 on success, or -1 signalling an exception. The
+ notification function won't be interrupted to perform another
+ asynchronous notification recursively, but it can still be
+ interrupted to switch threads if the global interpreter lock is
+ released, for example, if it calls back into Python code.
+
+ This function returns 0 on success in which case the notification
+ has been scheduled. Otherwise, for example if the notification
+ buffer is full, it returns -1 without setting any exception.
+
+ This function can be called on any thread, be it a Python thread
+ or some other system thread. If it is a Python thread, it doesn't
+ matter if it holds the global interpreter lock or not.
+ """
+ return -1
+
+thread_func = lltype.Ptr(lltype.FuncType([rffi.VOIDP], lltype.Void))
+ at cpython_api([thread_func, rffi.VOIDP], rffi.INT_real, error=-1)
+def PyThread_start_new_thread(space, func, arg):
+ return -1
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
@@ -429,3 +429,11 @@
w_char = api.PyUnicode_FromOrdinal(0xFFFF)
assert space.unwrap(w_char) == u'\uFFFF'
+ def test_replace(self, space, api):
+ w_str = space.wrap(u"abababab")
+ w_substr = space.wrap(u"a")
+ w_replstr = space.wrap(u"z")
+ assert u"zbzbabab" == space.unwrap(
+ api.PyUnicode_Replace(w_str, w_substr, w_replstr, 2))
+ assert u"zbzbzbzb" == space.unwrap(
+ api.PyUnicode_Replace(w_str, w_substr, w_replstr, -1))
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
@@ -548,6 +548,15 @@
@cpython_api([PyObject, PyObject], PyObject)
def PyUnicode_Join(space, w_sep, w_seq):
- """Join a sequence of strings using the given separator and return the resulting
- Unicode string."""
+ """Join a sequence of strings using the given separator and return
+ the resulting Unicode string."""
return space.call_method(w_sep, 'join', w_seq)
+
+ at cpython_api([PyObject, PyObject, PyObject, Py_ssize_t], PyObject)
+def PyUnicode_Replace(space, w_str, w_substr, w_replstr, maxcount):
+ """Replace at most maxcount occurrences of substr in str with replstr and
+ return the resulting Unicode object. maxcount == -1 means replace all
+ occurrences."""
+ return space.call_method(w_str, "replace", w_substr, w_replstr,
+ space.wrap(maxcount))
+
diff --git a/pypy/module/micronumpy/interp_boxes.py b/pypy/module/micronumpy/interp_boxes.py
--- a/pypy/module/micronumpy/interp_boxes.py
+++ b/pypy/module/micronumpy/interp_boxes.py
@@ -1,6 +1,6 @@
from pypy.interpreter.baseobjspace import Wrappable
from pypy.interpreter.error import operationerrfmt
-from pypy.interpreter.gateway import interp2app
+from pypy.interpreter.gateway import interp2app, unwrap_spec
from pypy.interpreter.typedef import TypeDef
from pypy.objspace.std.floattype import float_typedef
from pypy.objspace.std.inttype import int_typedef
@@ -29,7 +29,6 @@
def convert_to(self, dtype):
return dtype.box(self.value)
-
class W_GenericBox(Wrappable):
_attrs_ = ()
@@ -39,10 +38,10 @@
)
def descr_str(self, space):
- return self.descr_repr(space)
+ return space.wrap(self.get_dtype(space).itemtype.str_format(self))
- def descr_repr(self, space):
- return space.wrap(self.get_dtype(space).itemtype.str_format(self))
+ def descr_format(self, space, w_spec):
+ return space.format(self.item(space), w_spec)
def descr_int(self, space):
box = self.convert_to(W_LongBox.get_dtype(space))
@@ -187,6 +186,10 @@
descr__new__, get_dtype = new_dtype_getter("float64")
+ at unwrap_spec(self=W_GenericBox)
+def descr_index(space, self):
+ return space.index(self.item(space))
+
W_GenericBox.typedef = TypeDef("generic",
__module__ = "numpypy",
@@ -194,7 +197,8 @@
__new__ = interp2app(W_GenericBox.descr__new__.im_func),
__str__ = interp2app(W_GenericBox.descr_str),
- __repr__ = interp2app(W_GenericBox.descr_repr),
+ __repr__ = interp2app(W_GenericBox.descr_str),
+ __format__ = interp2app(W_GenericBox.descr_format),
__int__ = interp2app(W_GenericBox.descr_int),
__float__ = interp2app(W_GenericBox.descr_float),
__nonzero__ = interp2app(W_GenericBox.descr_nonzero),
@@ -245,6 +249,8 @@
W_BoolBox.typedef = TypeDef("bool_", W_GenericBox.typedef,
__module__ = "numpypy",
__new__ = interp2app(W_BoolBox.descr__new__.im_func),
+
+ __index__ = interp2app(descr_index),
)
W_NumberBox.typedef = TypeDef("number", W_GenericBox.typedef,
@@ -266,36 +272,43 @@
W_Int8Box.typedef = TypeDef("int8", W_SignedIntegerBox.typedef,
__module__ = "numpypy",
__new__ = interp2app(W_Int8Box.descr__new__.im_func),
+ __index__ = interp2app(descr_index),
)
W_UInt8Box.typedef = TypeDef("uint8", W_UnsignedIntegerBox.typedef,
__module__ = "numpypy",
__new__ = interp2app(W_UInt8Box.descr__new__.im_func),
+ __index__ = interp2app(descr_index),
)
W_Int16Box.typedef = TypeDef("int16", W_SignedIntegerBox.typedef,
__module__ = "numpypy",
__new__ = interp2app(W_Int16Box.descr__new__.im_func),
+ __index__ = interp2app(descr_index),
)
W_UInt16Box.typedef = TypeDef("uint16", W_UnsignedIntegerBox.typedef,
__module__ = "numpypy",
__new__ = interp2app(W_UInt16Box.descr__new__.im_func),
+ __index__ = interp2app(descr_index),
)
W_Int32Box.typedef = TypeDef("int32", (W_SignedIntegerBox.typedef,) + MIXIN_32,
__module__ = "numpypy",
__new__ = interp2app(W_Int32Box.descr__new__.im_func),
+ __index__ = interp2app(descr_index),
)
W_UInt32Box.typedef = TypeDef("uint32", W_UnsignedIntegerBox.typedef,
__module__ = "numpypy",
__new__ = interp2app(W_UInt32Box.descr__new__.im_func),
+ __index__ = interp2app(descr_index),
)
W_Int64Box.typedef = TypeDef("int64", (W_SignedIntegerBox.typedef,) + MIXIN_64,
__module__ = "numpypy",
__new__ = interp2app(W_Int64Box.descr__new__.im_func),
+ __index__ = interp2app(descr_index),
)
if LONG_BIT == 32:
@@ -308,6 +321,7 @@
W_UInt64Box.typedef = TypeDef("uint64", W_UnsignedIntegerBox.typedef,
__module__ = "numpypy",
__new__ = interp2app(W_UInt64Box.descr__new__.im_func),
+ __index__ = interp2app(descr_index),
)
W_InexactBox.typedef = TypeDef("inexact", W_NumberBox.typedef,
diff --git a/pypy/module/micronumpy/interp_support.py b/pypy/module/micronumpy/interp_support.py
--- a/pypy/module/micronumpy/interp_support.py
+++ b/pypy/module/micronumpy/interp_support.py
@@ -3,7 +3,7 @@
from pypy.rpython.lltypesystem import lltype, rffi
from pypy.module.micronumpy import interp_dtype
from pypy.objspace.std.strutil import strip_spaces
-
+from pypy.rlib import jit
FLOAT_SIZE = rffi.sizeof(lltype.Float)
@@ -72,11 +72,20 @@
"string is smaller than requested size"))
a = W_NDimArray(count, [count], dtype=dtype)
- for i in range(count):
+ fromstring_loop(a, count, dtype, itemsize, s)
+ return space.wrap(a)
+
+fromstring_driver = jit.JitDriver(greens=[], reds=['count', 'i', 'itemsize',
+ 'dtype', 's', 'a'])
+
+def fromstring_loop(a, count, dtype, itemsize, s):
+ i = 0
+ while i < count:
+ fromstring_driver.jit_merge_point(a=a, count=count, dtype=dtype,
+ itemsize=itemsize, s=s, i=i)
val = dtype.itemtype.runpack_str(s[i*itemsize:i*itemsize + itemsize])
a.dtype.setitem(a.storage, i, val)
-
- return space.wrap(a)
+ i += 1
@unwrap_spec(s=str, count=int, sep=str)
def fromstring(space, s, w_dtype=None, count=-1, sep=''):
diff --git a/pypy/module/micronumpy/test/test_dtypes.py b/pypy/module/micronumpy/test/test_dtypes.py
--- a/pypy/module/micronumpy/test/test_dtypes.py
+++ b/pypy/module/micronumpy/test/test_dtypes.py
@@ -371,6 +371,8 @@
assert type(a[1]) is numpy.float64
assert numpy.dtype(float).type is numpy.float64
+ assert "{:3f}".format(numpy.float64(3)) == "3.000000"
+
assert numpy.float64(2.0) == 2.0
assert numpy.float64('23.4') == numpy.float64(23.4)
raises(ValueError, numpy.float64, '23.2df')
@@ -387,9 +389,9 @@
assert b.m() == 12
def test_long_as_index(self):
- skip("waiting for removal of multimethods of __index__")
- from _numpypy import int_
+ from _numpypy import int_, float64
assert (1, 2, 3)[int_(1)] == 2
+ raises(TypeError, lambda: (1, 2, 3)[float64(1)])
def test_int(self):
import sys
diff --git a/pypy/module/micronumpy/test/test_zjit.py b/pypy/module/micronumpy/test/test_zjit.py
--- a/pypy/module/micronumpy/test/test_zjit.py
+++ b/pypy/module/micronumpy/test/test_zjit.py
@@ -479,38 +479,3 @@
'int_sub': 3,
'jump': 1,
'setinteriorfield_raw': 1})
-
-
-class TestNumpyOld(LLJitMixin):
- def setup_class(cls):
- py.test.skip("old")
- from pypy.module.micronumpy.compile import FakeSpace
- from pypy.module.micronumpy.interp_dtype import get_dtype_cache
-
- cls.space = FakeSpace()
- cls.float64_dtype = get_dtype_cache(cls.space).w_float64dtype
-
- def test_int32_sum(self):
- py.test.skip("pypy/jit/backend/llimpl.py needs to be changed to "
- "deal correctly with int dtypes for this test to "
- "work. skip for now until someone feels up to the task")
- space = self.space
- float64_dtype = self.float64_dtype
- int32_dtype = self.int32_dtype
-
- def f(n):
- if NonConstant(False):
- dtype = float64_dtype
- else:
- dtype = int32_dtype
- ar = W_NDimArray(n, [n], dtype=dtype)
- i = 0
- while i < n:
- ar.get_concrete().setitem(i, int32_dtype.box(7))
- i += 1
- v = ar.descr_add(space, ar).descr_sum(space)
- assert isinstance(v, IntObject)
- return v.intval
-
- result = self.meta_interp(f, [5], listops=True, backendopt=True)
- assert result == f(5)
diff --git a/pypy/module/test_lib_pypy/ctypes_tests/test_fastpath.py b/pypy/module/test_lib_pypy/ctypes_tests/test_fastpath.py
--- a/pypy/module/test_lib_pypy/ctypes_tests/test_fastpath.py
+++ b/pypy/module/test_lib_pypy/ctypes_tests/test_fastpath.py
@@ -97,6 +97,16 @@
tf_b.errcheck = errcheck
assert tf_b(-126) == 'hello'
+ def test_array_to_ptr(self):
+ ARRAY = c_int * 8
+ func = dll._testfunc_ai8
+ func.restype = POINTER(c_int)
+ func.argtypes = [ARRAY]
+ array = ARRAY(1, 2, 3, 4, 5, 6, 7, 8)
+ ptr = func(array)
+ assert ptr[0] == 1
+ assert ptr[7] == 8
+
class TestFallbackToSlowpath(BaseCTypesTestChecker):
diff --git a/pypy/module/test_lib_pypy/ctypes_tests/test_prototypes.py b/pypy/module/test_lib_pypy/ctypes_tests/test_prototypes.py
--- a/pypy/module/test_lib_pypy/ctypes_tests/test_prototypes.py
+++ b/pypy/module/test_lib_pypy/ctypes_tests/test_prototypes.py
@@ -246,6 +246,14 @@
def func(): pass
CFUNCTYPE(None, c_int * 3)(func)
+ def test_array_to_ptr_wrongtype(self):
+ ARRAY = c_byte * 8
+ func = testdll._testfunc_ai8
+ func.restype = POINTER(c_int)
+ func.argtypes = [c_int * 8]
+ array = ARRAY(1, 2, 3, 4, 5, 6, 7, 8)
+ py.test.raises(ArgumentError, "func(array)")
+
################################################################
if __name__ == '__main__':
diff --git a/pypy/module/test_lib_pypy/test_datetime.py b/pypy/module/test_lib_pypy/test_datetime.py
--- a/pypy/module/test_lib_pypy/test_datetime.py
+++ b/pypy/module/test_lib_pypy/test_datetime.py
@@ -3,7 +3,7 @@
import py
import time
-import datetime
+from lib_pypy import datetime
import copy
import os
@@ -43,4 +43,4 @@
dt = datetime.datetime.utcnow()
assert type(dt.microsecond) is int
- copy.copy(dt)
\ No newline at end of file
+ copy.copy(dt)
diff --git a/pypy/objspace/std/dictmultiobject.py b/pypy/objspace/std/dictmultiobject.py
--- a/pypy/objspace/std/dictmultiobject.py
+++ b/pypy/objspace/std/dictmultiobject.py
@@ -142,6 +142,17 @@
else:
return result
+ def popitem(self, w_dict):
+ # this is a bad implementation: if we call popitem() repeatedly,
+ # it ends up taking n**2 time, because the next() calls below
+ # will take longer and longer. But all interesting strategies
+ # provide a better one.
+ space = self.space
+ iterator = self.iter(w_dict)
+ w_key, w_value = iterator.next()
+ self.delitem(w_dict, w_key)
+ return (w_key, w_value)
+
def clear(self, w_dict):
strategy = self.space.fromcache(EmptyDictStrategy)
storage = strategy.get_empty_storage()
diff --git a/pypy/objspace/std/dictproxyobject.py b/pypy/objspace/std/dictproxyobject.py
--- a/pypy/objspace/std/dictproxyobject.py
+++ b/pypy/objspace/std/dictproxyobject.py
@@ -3,7 +3,7 @@
from pypy.objspace.std.dictmultiobject import W_DictMultiObject, IteratorImplementation
from pypy.objspace.std.dictmultiobject import DictStrategy
from pypy.objspace.std.typeobject import unwrap_cell
-from pypy.interpreter.error import OperationError
+from pypy.interpreter.error import OperationError, operationerrfmt
from pypy.rlib import rerased
@@ -44,7 +44,8 @@
raise
if not w_type.is_cpytype():
raise
- # xxx obscure workaround: allow cpyext to write to type->tp_dict.
+ # xxx obscure workaround: allow cpyext to write to type->tp_dict
+ # xxx even in the case of a builtin type.
# xxx like CPython, we assume that this is only done early after
# xxx the type is created, and we don't invalidate any cache.
w_type.dict_w[key] = w_value
@@ -86,8 +87,14 @@
for (key, w_value) in self.unerase(w_dict.dstorage).dict_w.iteritems()]
def clear(self, w_dict):
- self.unerase(w_dict.dstorage).dict_w.clear()
- self.unerase(w_dict.dstorage).mutated(None)
+ space = self.space
+ w_type = self.unerase(w_dict.dstorage)
+ if (not space.config.objspace.std.mutable_builtintypes
+ and not w_type.is_heaptype()):
+ msg = "can't clear dictionary of type '%s'"
+ raise operationerrfmt(space.w_TypeError, msg, w_type.name)
+ w_type.dict_w.clear()
+ w_type.mutated(None)
class DictProxyIteratorImplementation(IteratorImplementation):
def __init__(self, space, strategy, dictimplementation):
diff --git a/pypy/objspace/std/test/test_dictproxy.py b/pypy/objspace/std/test/test_dictproxy.py
--- a/pypy/objspace/std/test/test_dictproxy.py
+++ b/pypy/objspace/std/test/test_dictproxy.py
@@ -22,6 +22,9 @@
assert NotEmpty.string == 1
raises(TypeError, 'NotEmpty.__dict__.setdefault(15, 1)')
+ key, value = NotEmpty.__dict__.popitem()
+ assert (key == 'a' and value == 1) or (key == 'b' and value == 4)
+
def test_dictproxyeq(self):
class a(object):
pass
@@ -43,6 +46,11 @@
assert s1 == s2
assert s1.startswith('{') and s1.endswith('}')
+ def test_immutable_dict_on_builtin_type(self):
+ raises(TypeError, "int.__dict__['a'] = 1")
+ raises(TypeError, int.__dict__.popitem)
+ raises(TypeError, int.__dict__.clear)
+
class AppTestUserObjectMethodCache(AppTestUserObject):
def setup_class(cls):
cls.space = gettestobjspace(
diff --git a/pypy/objspace/std/test/test_typeobject.py b/pypy/objspace/std/test/test_typeobject.py
--- a/pypy/objspace/std/test/test_typeobject.py
+++ b/pypy/objspace/std/test/test_typeobject.py
@@ -993,7 +993,9 @@
raises(TypeError, setattr, list, 'append', 42)
raises(TypeError, setattr, list, 'foobar', 42)
raises(TypeError, delattr, dict, 'keys')
-
+ raises(TypeError, 'int.__dict__["a"] = 1')
+ raises(TypeError, 'int.__dict__.clear()')
+
def test_nontype_in_mro(self):
class OldStyle:
pass
diff --git a/pypy/rlib/debug.py b/pypy/rlib/debug.py
--- a/pypy/rlib/debug.py
+++ b/pypy/rlib/debug.py
@@ -19,14 +19,22 @@
hop.exception_cannot_occur()
hop.genop('debug_assert', vlist)
-def fatalerror(msg, traceback=False):
+def fatalerror(msg):
+ # print the RPython traceback and abort with a fatal error
from pypy.rpython.lltypesystem import lltype
from pypy.rpython.lltypesystem.lloperation import llop
- if traceback:
- llop.debug_print_traceback(lltype.Void)
+ llop.debug_print_traceback(lltype.Void)
llop.debug_fatalerror(lltype.Void, msg)
fatalerror._dont_inline_ = True
-fatalerror._annspecialcase_ = 'specialize:arg(1)'
+fatalerror._annenforceargs_ = [str]
+
+def fatalerror_notb(msg):
+ # a variant of fatalerror() that doesn't print the RPython traceback
+ from pypy.rpython.lltypesystem import lltype
+ from pypy.rpython.lltypesystem.lloperation import llop
+ llop.debug_fatalerror(lltype.Void, msg)
+fatalerror_notb._dont_inline_ = True
+fatalerror_notb._annenforceargs_ = [str]
class DebugLog(list):
diff --git a/pypy/rlib/jit.py b/pypy/rlib/jit.py
--- a/pypy/rlib/jit.py
+++ b/pypy/rlib/jit.py
@@ -450,6 +450,7 @@
assert v in self.reds
self._alllivevars = dict.fromkeys(
[name for name in self.greens + self.reds if '.' not in name])
+ self._heuristic_order = {} # check if 'reds' and 'greens' are ordered
self._make_extregistryentries()
self.get_jitcell_at = get_jitcell_at
self.set_jitcell_at = set_jitcell_at
@@ -461,13 +462,59 @@
def _freeze_(self):
return True
+ def _check_arguments(self, livevars):
+ assert dict.fromkeys(livevars) == self._alllivevars
+ # check heuristically that 'reds' and 'greens' are ordered as
+ # the JIT will need them to be: first INTs, then REFs, then
+ # FLOATs.
+ if len(self._heuristic_order) < len(livevars):
+ from pypy.rlib.rarithmetic import (r_singlefloat, r_longlong,
+ r_ulonglong)
+ added = False
+ for var, value in livevars.items():
+ if var not in self._heuristic_order:
+ if isinstance(value, (r_longlong, r_ulonglong)):
+ assert 0, ("should not pass a r_longlong argument for "
+ "now, because on 32-bit machines it would "
+ "need to be ordered as a FLOAT")
+ elif isinstance(value, (int, long, r_singlefloat)):
+ kind = '1:INT'
+ elif isinstance(value, float):
+ kind = '3:FLOAT'
+ elif isinstance(value, (str, unicode)) and len(value) != 1:
+ kind = '2:REF'
+ elif isinstance(value, (list, dict)):
+ kind = '2:REF'
+ elif (hasattr(value, '__class__')
+ and value.__class__.__module__ != '__builtin__'):
+ if hasattr(value, '_freeze_'):
+ continue # value._freeze_() is better not called
+ elif getattr(value, '_alloc_flavor_', 'gc') == 'gc':
+ kind = '2:REF'
+ else:
+ kind = '1:INT'
+ else:
+ continue
+ self._heuristic_order[var] = kind
+ added = True
+ if added:
+ for color in ('reds', 'greens'):
+ lst = getattr(self, color)
+ allkinds = [self._heuristic_order.get(name, '?')
+ for name in lst]
+ kinds = [k for k in allkinds if k != '?']
+ assert kinds == sorted(kinds), (
+ "bad order of %s variables in the jitdriver: "
+ "must be INTs, REFs, FLOATs; got %r" %
+ (color, allkinds))
+
def jit_merge_point(_self, **livevars):
# special-cased by ExtRegistryEntry
- assert dict.fromkeys(livevars) == _self._alllivevars
+ _self._check_arguments(livevars)
def can_enter_jit(_self, **livevars):
# special-cased by ExtRegistryEntry
- assert dict.fromkeys(livevars) == _self._alllivevars
+ _self._check_arguments(livevars)
def loop_header(self):
# special-cased by ExtRegistryEntry
diff --git a/pypy/rlib/objectmodel.py b/pypy/rlib/objectmodel.py
--- a/pypy/rlib/objectmodel.py
+++ b/pypy/rlib/objectmodel.py
@@ -23,9 +23,11 @@
class _Specialize(object):
def memo(self):
- """ Specialize functions based on argument values. All arguments has
- to be constant at the compile time. The whole function call is replaced
- by a call result then.
+ """ Specialize the function based on argument values. All arguments
+ have to be either constants or PBCs (i.e. instances of classes with a
+ _freeze_ method returning True). The function call is replaced by
+ just its result, or in case several PBCs are used, by some fast
+ look-up of the result.
"""
def decorated_func(func):
func._annspecialcase_ = 'specialize:memo'
@@ -33,8 +35,8 @@
return decorated_func
def arg(self, *args):
- """ Specialize function based on values of given positions of arguments.
- They must be compile-time constants in order to work.
+ """ Specialize the function based on the values of given positions
+ of arguments. They must be compile-time constants in order to work.
There will be a copy of provided function for each combination
of given arguments on positions in args (that can lead to
@@ -82,8 +84,7 @@
return decorated_func
def ll_and_arg(self, *args):
- """ This is like ll(), but instead of specializing on all arguments,
- specializes on only the arguments at the given positions
+ """ This is like ll(), and additionally like arg(...).
"""
def decorated_func(func):
func._annspecialcase_ = 'specialize:ll_and_arg' + self._wrap(args)
diff --git a/pypy/rlib/test/test_jit.py b/pypy/rlib/test/test_jit.py
--- a/pypy/rlib/test/test_jit.py
+++ b/pypy/rlib/test/test_jit.py
@@ -146,6 +146,38 @@
res = self.interpret(f, [-234])
assert res == 1
+ def test_argument_order_ok(self):
+ myjitdriver = JitDriver(greens=['i1', 'r1', 'f1'], reds=[])
+ class A(object):
+ pass
+ myjitdriver.jit_merge_point(i1=42, r1=A(), f1=3.5)
+ # assert did not raise
+
+ def test_argument_order_wrong(self):
+ myjitdriver = JitDriver(greens=['r1', 'i1', 'f1'], reds=[])
+ class A(object):
+ pass
+ e = raises(AssertionError,
+ myjitdriver.jit_merge_point, i1=42, r1=A(), f1=3.5)
+
+ def test_argument_order_more_precision_later(self):
+ myjitdriver = JitDriver(greens=['r1', 'i1', 'r2', 'f1'], reds=[])
+ class A(object):
+ pass
+ myjitdriver.jit_merge_point(i1=42, r1=None, r2=None, f1=3.5)
+ e = raises(AssertionError,
+ myjitdriver.jit_merge_point, i1=42, r1=A(), r2=None, f1=3.5)
+ assert "got ['2:REF', '1:INT', '?', '3:FLOAT']" in repr(e.value)
+
+ def test_argument_order_more_precision_later_2(self):
+ myjitdriver = JitDriver(greens=['r1', 'i1', 'r2', 'f1'], reds=[])
+ class A(object):
+ pass
+ myjitdriver.jit_merge_point(i1=42, r1=None, r2=A(), f1=3.5)
+ e = raises(AssertionError,
+ myjitdriver.jit_merge_point, i1=42, r1=A(), r2=None, f1=3.5)
+ assert "got ['2:REF', '1:INT', '2:REF', '3:FLOAT']" in repr(e.value)
+
class TestJITLLtype(BaseTestJIT, LLRtypeMixin):
pass
diff --git a/pypy/rpython/memory/gc/generation.py b/pypy/rpython/memory/gc/generation.py
--- a/pypy/rpython/memory/gc/generation.py
+++ b/pypy/rpython/memory/gc/generation.py
@@ -41,8 +41,8 @@
# the following values override the default arguments of __init__ when
# translating to a real backend.
- TRANSLATION_PARAMS = {'space_size': 8*1024*1024, # XXX adjust
- 'nursery_size': 896*1024,
+ TRANSLATION_PARAMS = {'space_size': 8*1024*1024, # 8 MB
+ 'nursery_size': 3*1024*1024, # 3 MB
'min_nursery_size': 48*1024,
'auto_nursery_size': True}
@@ -92,8 +92,9 @@
# the GC is fully setup now. The rest can make use of it.
if self.auto_nursery_size:
newsize = nursery_size_from_env()
- if newsize <= 0:
- newsize = env.estimate_best_nursery_size()
+ #if newsize <= 0:
+ # ---disabled--- just use the default value.
+ # newsize = env.estimate_best_nursery_size()
if newsize > 0:
self.set_nursery_size(newsize)
diff --git a/pypy/tool/jitlogparser/parser.py b/pypy/tool/jitlogparser/parser.py
--- a/pypy/tool/jitlogparser/parser.py
+++ b/pypy/tool/jitlogparser/parser.py
@@ -387,7 +387,7 @@
m = re.search('guard \d+', comm)
name = m.group(0)
else:
- name = comm[2:comm.find(':')-1]
+ name = " ".join(comm[2:].split(" ", 2)[:2])
if name in dumps:
bname, start_ofs, dump = dumps[name]
loop.force_asm = (lambda dump=dump, start_ofs=start_ofs,
diff --git a/pypy/tool/release/package.py b/pypy/tool/release/package.py
--- a/pypy/tool/release/package.py
+++ b/pypy/tool/release/package.py
@@ -82,6 +82,9 @@
for file in ['LICENSE', 'README']:
shutil.copy(str(basedir.join(file)), str(pypydir))
pypydir.ensure('include', dir=True)
+ if sys.platform == 'win32':
+ shutil.copyfile(str(pypy_c.dirpath().join("libpypy-c.lib")),
+ str(pypydir.join('include/python27.lib')))
# we want to put there all *.h and *.inl from trunk/include
# and from pypy/_interfaces
includedir = basedir.join('include')
diff --git a/pypy/translator/c/gcc/trackgcroot.py b/pypy/translator/c/gcc/trackgcroot.py
--- a/pypy/translator/c/gcc/trackgcroot.py
+++ b/pypy/translator/c/gcc/trackgcroot.py
@@ -472,7 +472,7 @@
IGNORE_OPS_WITH_PREFIXES = dict.fromkeys([
'cmp', 'test', 'set', 'sahf', 'lahf', 'cld', 'std',
- 'rep', 'movs', 'lods', 'stos', 'scas', 'cwde', 'prefetch',
+ 'rep', 'movs', 'movhp', 'lods', 'stos', 'scas', 'cwde', 'prefetch',
# floating-point operations cannot produce GC pointers
'f',
'cvt', 'ucomi', 'comi', 'subs', 'subp' , 'adds', 'addp', 'xorp',
@@ -484,7 +484,7 @@
'shl', 'shr', 'sal', 'sar', 'rol', 'ror', 'mul', 'imul', 'div', 'idiv',
'bswap', 'bt', 'rdtsc',
'punpck', 'pshufd', 'pcmp', 'pand', 'psllw', 'pslld', 'psllq',
- 'paddq', 'pinsr',
+ 'paddq', 'pinsr', 'pmul', 'psrl',
# sign-extending moves should not produce GC pointers
'cbtw', 'cwtl', 'cwtd', 'cltd', 'cltq', 'cqto',
# zero-extending moves should not produce GC pointers
diff --git a/pypy/translator/driver.py b/pypy/translator/driver.py
--- a/pypy/translator/driver.py
+++ b/pypy/translator/driver.py
@@ -559,6 +559,9 @@
newsoname = newexename.new(basename=soname.basename)
shutil.copy(str(soname), str(newsoname))
self.log.info("copied: %s" % (newsoname,))
+ if sys.platform == 'win32':
+ shutil.copyfile(str(soname.new(ext='lib')),
+ str(newsoname.new(ext='lib')))
self.c_entryp = newexename
self.log.info('usession directory: %s' % (udir,))
self.log.info("created: %s" % (self.c_entryp,))
More information about the pypy-commit
mailing list