Author: Matti Picus <[email protected]>
Branch: cpyext-add_newdoc
Changeset: r91785:b2f03ffd8457
Date: 2017-07-07 10:53 +0300
http://bitbucket.org/pypy/pypy/changeset/b2f03ffd8457/
Log: merge default into branch
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
@@ -21,3 +21,7 @@
.. branch: issue-2592
CPyext PyListObject.pop must return the value
+
+.. branch: cpyext-hash_notimpl
+
+If ``tp_hash`` is ``PyObject_HashNotImplemented``, set
``obj.__dict__['__hash__']`` to None
diff --git a/pypy/module/_cffi_backend/errorbox.py
b/pypy/module/_cffi_backend/errorbox.py
--- a/pypy/module/_cffi_backend/errorbox.py
+++ b/pypy/module/_cffi_backend/errorbox.py
@@ -86,8 +86,6 @@
return
w_text = self.space.call_function(w_done)
- # XXX Python 3: MessageBoxA() => MessageBoxW()
-
p = rffi.str2charp(self.space.bytes_w(w_text),
track_allocation=False)
if self.text_p:
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -456,13 +456,15 @@
return decorate
def api_func_from_cdef(func, cdef, cts,
- error=_NOT_SPECIFIED, header=DEFAULT_HEADER):
+ error=_NOT_SPECIFIED, header=DEFAULT_HEADER,
+ result_is_ll=False):
func._always_inline_ = 'try'
cdecl = cts.parse_func(cdef)
RESULT = cdecl.get_llresult(cts)
api_function = ApiFunction(
cdecl.get_llargs(cts), RESULT, func,
- error=_compute_error(error, RESULT), cdecl=cdecl)
+ error=_compute_error(error, RESULT), cdecl=cdecl,
+ result_is_ll=result_is_ll)
FUNCTIONS_BY_HEADER[header][cdecl.name] = api_function
unwrapper = api_function.get_unwrapper()
unwrapper.func = func
@@ -656,10 +658,12 @@
class CpyextTypeSpace(CTypeSpace):
- def decl(self, cdef, error=_NOT_SPECIFIED, header=DEFAULT_HEADER):
+ def decl(self, cdef, error=_NOT_SPECIFIED, header=DEFAULT_HEADER,
+ result_is_ll=False):
def decorate(func):
return api_func_from_cdef(
- func, cdef, self, error=error, header=header)
+ func, cdef, self, error=error, header=header,
+ result_is_ll=result_is_ll)
return decorate
diff --git a/pypy/module/cpyext/buffer.py b/pypy/module/cpyext/buffer.py
--- a/pypy/module/cpyext/buffer.py
+++ b/pypy/module/cpyext/buffer.py
@@ -1,10 +1,171 @@
from rpython.rtyper.lltypesystem import rffi, lltype
+from rpython.rlib import rgc # Force registration of gc.collect
+from rpython.rlib.buffer import RawBuffer
from pypy.interpreter.error import oefmt
+from pypy.interpreter.buffer import BufferView
from pypy.module.cpyext.api import (
- cpython_api, CANNOT_FAIL, cts, Py_buffer,
- Py_ssize_t, Py_ssize_tP, generic_cpy_call,
+ cpython_api, Py_buffer, Py_ssize_t, Py_ssize_tP, CONST_STRINGP, cts,
+ generic_cpy_call,
PyBUF_WRITABLE, PyBUF_FORMAT, PyBUF_ND, PyBUF_STRIDES)
-from pypy.module.cpyext.pyobject import PyObject, Py_IncRef
+from pypy.module.cpyext.typeobjectdefs import releasebufferproc
+from pypy.module.cpyext.pyobject import PyObject, incref, decref, as_pyobj
+
+class CBuffer(RawBuffer):
+ _immutable_ = True
+ def __init__(self, view):
+ self.view = view
+ self.readonly = view.readonly
+
+ def getlength(self):
+ return self.view.getlength()
+
+ def getitem(self, index):
+ return self.view.ptr[index]
+
+ def getslice(self, start, stop, step, size):
+ assert step == 1
+ assert stop - start == size
+ ptr = rffi.ptradd(cts.cast('char *', self.view.ptr), start)
+ return rffi.charpsize2str(ptr, size)
+
+ def setitem(self, index, char):
+ self.view.ptr[index] = char
+
+ def setslice(self, index, s):
+ assert s is not None
+ ptr = rffi.ptradd(cts.cast('char *', self.view.ptr), index)
+ rffi.str2chararray(s, ptr, len(s))
+
+ def get_raw_address(self):
+ return cts.cast('char *', self.view.ptr)
+
+class CPyBuffer(BufferView):
+ # Similar to Py_buffer
+ _immutable_ = True
+
+ def __init__(self, space, ptr, size, w_obj, format='B', shape=None,
+ strides=None, ndim=1, itemsize=1, readonly=True,
+ needs_decref=False,
+ releasebufferproc=rffi.cast(rffi.VOIDP, 0)):
+ self.space = space
+ self.ptr = ptr
+ self.size = size
+ self.w_obj = w_obj # kept alive
+ self.pyobj = as_pyobj(space, w_obj)
+ self.format = format
+ self.ndim = ndim
+ self.itemsize = itemsize
+
+ if not shape:
+ self.shape = [size]
+ else:
+ self.shape = shape
+ if not strides:
+ self.strides = [1]
+ else:
+ self.strides = strides
+ self.readonly = readonly
+ self.needs_decref = needs_decref
+ self.releasebufferproc = releasebufferproc
+
+ def releasebuffer(self):
+ if self.pyobj:
+ if self.needs_decref:
+ if self.releasebufferproc:
+ func_target = rffi.cast(releasebufferproc,
self.releasebufferproc)
+ with lltype.scoped_alloc(Py_buffer) as pybuf:
+ pybuf.c_buf = self.ptr
+ pybuf.c_len = self.size
+ pybuf.c_ndim = cts.cast('int', self.ndim)
+ pybuf.c_shape = cts.cast('Py_ssize_t*', pybuf.c__shape)
+ pybuf.c_strides = cts.cast('Py_ssize_t*',
pybuf.c__strides)
+ for i in range(self.ndim):
+ pybuf.c_shape[i] = self.shape[i]
+ pybuf.c_strides[i] = self.strides[i]
+ if self.format:
+ pybuf.c_format = rffi.str2charp(self.format)
+ else:
+ pybuf.c_format = rffi.str2charp("B")
+ generic_cpy_call(self.space, func_target, self.pyobj,
pybuf)
+ decref(self.space, self.pyobj)
+ self.pyobj = lltype.nullptr(PyObject.TO)
+ else:
+ #do not call twice
+ return
+
+ def getlength(self):
+ return self.size
+
+ def getbytes(self, start, size):
+ return ''.join([self.ptr[i] for i in range(start, start + size)])
+
+ def setbytes(self, start, string):
+ # absolutely no safety checks, what could go wrong?
+ for i in range(len(string)):
+ self.ptr[start + i] = string[i]
+
+ def as_str(self):
+ return CBuffer(self).as_str()
+
+ def as_readbuf(self):
+ return CBuffer(self)
+
+ def as_writebuf(self):
+ assert not self.readonly
+ return CBuffer(self)
+
+ def get_raw_address(self):
+ return rffi.cast(rffi.CCHARP, self.ptr)
+
+ def getformat(self):
+ return self.format
+
+ def getshape(self):
+ return self.shape
+
+ def getstrides(self):
+ return self.strides
+
+ def getitemsize(self):
+ return self.itemsize
+
+ def getndim(self):
+ return self.ndim
+
+class FQ(rgc.FinalizerQueue):
+ Class = CPyBuffer
+ def finalizer_trigger(self):
+ while 1:
+ buf = self.next_dead()
+ if not buf:
+ break
+ buf.releasebuffer()
+
+fq = FQ()
+
+
+@cpython_api([PyObject, CONST_STRINGP, Py_ssize_tP], rffi.INT_real, error=-1)
+def PyObject_AsCharBuffer(space, obj, bufferp, sizep):
+ """Returns a pointer to a read-only memory location usable as
+ character-based input. The obj argument must support the single-segment
+ character buffer interface. On success, returns 0, sets buffer to the
+ memory location and size to the buffer length. Returns -1 and sets a
+ TypeError on error.
+ """
+ pto = obj.c_ob_type
+ pb = pto.c_tp_as_buffer
+ if not (pb and pb.c_bf_getreadbuffer and pb.c_bf_getsegcount):
+ raise oefmt(space.w_TypeError, "expected a character buffer object")
+ if generic_cpy_call(space, pb.c_bf_getsegcount,
+ obj, lltype.nullptr(Py_ssize_tP.TO)) != 1:
+ raise oefmt(space.w_TypeError,
+ "expected a single-segment buffer object")
+ size = generic_cpy_call(space, pb.c_bf_getcharbuffer,
+ obj, 0, bufferp)
+ if size < 0:
+ return -1
+ sizep[0] = size
+ return 0
@cpython_api([lltype.Ptr(Py_buffer), PyObject, rffi.VOIDP, Py_ssize_t,
lltype.Signed, lltype.Signed], rffi.INT, error=-1)
@@ -20,7 +181,7 @@
view.c_len = length
view.c_obj = obj
if obj:
- Py_IncRef(space, obj)
+ incref(space, obj)
view.c_itemsize = 1
rffi.setintfield(view, 'c_readonly', readonly)
rffi.setintfield(view, 'c_ndim', 1)
diff --git a/pypy/module/cpyext/include/memoryobject.h
b/pypy/module/cpyext/include/memoryobject.h
--- a/pypy/module/cpyext/include/memoryobject.h
+++ b/pypy/module/cpyext/include/memoryobject.h
@@ -5,14 +5,7 @@
extern "C" {
#endif
-/* The struct is declared here but it shouldn't
- be considered public. Don't access those fields directly,
- use the functions instead! */
-typedef struct {
- PyObject_HEAD
- Py_buffer view;
-} PyMemoryViewObject;
-
+#include "cpyext_memoryobject.h"
/* Get a pointer to the memoryview's private copy of the exporter's buffer. */
#define PyMemoryView_GET_BUFFER(op) (&((PyMemoryViewObject *)(op))->view)
diff --git a/pypy/module/cpyext/memoryobject.py
b/pypy/module/cpyext/memoryobject.py
--- a/pypy/module/cpyext/memoryobject.py
+++ b/pypy/module/cpyext/memoryobject.py
@@ -1,29 +1,22 @@
-from rpython.rlib.objectmodel import keepalive_until_here
-from pypy.interpreter.error import oefmt
from pypy.module.cpyext.api import (
- cpython_api, Py_buffer, CANNOT_FAIL, Py_MAX_FMT, Py_MAX_NDIMS,
- build_type_checkers, Py_ssize_tP, PyObjectFields, cpython_struct,
- bootstrap_function, Py_bufferP, slot_function, generic_cpy_call)
+ cpython_api, CANNOT_FAIL, Py_MAX_FMT, Py_MAX_NDIMS, build_type_checkers,
+ Py_ssize_tP, cts, parse_dir, bootstrap_function, Py_bufferP, slot_function)
from pypy.module.cpyext.pyobject import (
- PyObject, make_ref, as_pyobj, decref, from_ref, make_typedescr,
+ PyObject, make_ref, decref, from_ref, make_typedescr,
get_typedescr, track_reference)
from rpython.rtyper.lltypesystem import lltype, rffi
from rpython.rlib.rarithmetic import widen
from pypy.objspace.std.memoryobject import W_MemoryView
from pypy.module.cpyext.object import _dealloc
from pypy.module.cpyext.import_ import PyImport_Import
+from pypy.module.cpyext.buffer import CPyBuffer, fq
+
+cts.parse_header(parse_dir / 'cpyext_memoryobject.h')
+PyMemoryViewObject = cts.gettype('PyMemoryViewObject*')
PyMemoryView_Check, PyMemoryView_CheckExact = build_type_checkers("MemoryView")
-PyMemoryViewObjectStruct = lltype.ForwardReference()
-PyMemoryViewObject = lltype.Ptr(PyMemoryViewObjectStruct)
-PyMemoryViewObjectFields = PyObjectFields + \
- (("view", Py_buffer),)
-cpython_struct(
- "PyMemoryViewObject", PyMemoryViewObjectFields, PyMemoryViewObjectStruct,
- level=2)
-
@bootstrap_function
def init_memoryobject(space):
"Type description of PyDictObject"
@@ -32,7 +25,7 @@
attach=memory_attach,
dealloc=memory_dealloc,
realize=memory_realize,
- )
+ )
def memory_attach(space, py_obj, w_obj, w_userdata=None):
"""
@@ -61,7 +54,6 @@
"""
Creates the memory object in the interpreter
"""
- from pypy.module.cpyext.slotdefs import CPyBuffer, fq
py_mem = rffi.cast(PyMemoryViewObject, obj)
view = py_mem.c_view
ndim = widen(view.c_ndim)
diff --git a/pypy/module/cpyext/object.py b/pypy/module/cpyext/object.py
--- a/pypy/module/cpyext/object.py
+++ b/pypy/module/cpyext/object.py
@@ -3,7 +3,7 @@
cpython_api, generic_cpy_call, CANNOT_FAIL, Py_ssize_t, Py_ssize_tP,
PyVarObject, size_t, slot_function,
Py_TPFLAGS_HEAPTYPE, Py_LT, Py_LE, Py_EQ, Py_NE, Py_GT,
- Py_GE, CONST_STRING, CONST_STRINGP, FILEP, fwrite)
+ Py_GE, CONST_STRING, FILEP, fwrite)
from pypy.module.cpyext.pyobject import (
PyObject, PyObjectP, from_ref, Py_IncRef, Py_DecRef,
get_typedescr)
@@ -432,30 +432,6 @@
is active then NULL is returned but PyErr_Occurred() will return false."""
return space.call_function(space.builtin.get('dir'), w_o)
-@cpython_api([PyObject, CONST_STRINGP, Py_ssize_tP], rffi.INT_real, error=-1)
-def PyObject_AsCharBuffer(space, obj, bufferp, sizep):
- """Returns a pointer to a read-only memory location usable as
- character-based input. The obj argument must support the single-segment
- character buffer interface. On success, returns 0, sets buffer to the
- memory location and size to the buffer length. Returns -1 and sets a
- TypeError on error.
- """
- pto = obj.c_ob_type
-
- pb = pto.c_tp_as_buffer
- if not (pb and pb.c_bf_getreadbuffer and pb.c_bf_getsegcount):
- raise oefmt(space.w_TypeError, "expected a character buffer object")
- if generic_cpy_call(space, pb.c_bf_getsegcount,
- obj, lltype.nullptr(Py_ssize_tP.TO)) != 1:
- raise oefmt(space.w_TypeError,
- "expected a single-segment buffer object")
- size = generic_cpy_call(space, pb.c_bf_getcharbuffer,
- obj, 0, bufferp)
- if size < 0:
- return -1
- sizep[0] = size
- return 0
-
# Also in include/object.h
Py_PRINT_RAW = 1 # No string quotes etc.
diff --git a/pypy/module/cpyext/parse/cpyext_memoryobject.h
b/pypy/module/cpyext/parse/cpyext_memoryobject.h
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/parse/cpyext_memoryobject.h
@@ -0,0 +1,7 @@
+/* The struct is declared here but it shouldn't
+ be considered public. Don't access those fields directly,
+ use the functions instead! */
+typedef struct {
+ PyObject_HEAD
+ Py_buffer view;
+} PyMemoryViewObject;
diff --git a/pypy/module/cpyext/slotdefs.py b/pypy/module/cpyext/slotdefs.py
--- a/pypy/module/cpyext/slotdefs.py
+++ b/pypy/module/cpyext/slotdefs.py
@@ -4,7 +4,6 @@
from rpython.rtyper.lltypesystem import rffi, lltype
from rpython.rlib.rarithmetic import widen
-from rpython.rlib import rgc # Force registration of gc.collect
from pypy.module.cpyext.api import (
slot_function, generic_cpy_call, PyObject, Py_ssize_t,
Py_TPFLAGS_CHECKTYPES, Py_buffer, Py_bufferP, PyTypeObjectPtr, cts)
@@ -13,22 +12,20 @@
getattrfunc, getattrofunc, setattrofunc, lenfunc, ssizeargfunc, inquiry,
ssizessizeargfunc, ssizeobjargproc, iternextfunc, initproc, richcmpfunc,
cmpfunc, hashfunc, descrgetfunc, descrsetfunc, objobjproc, objobjargproc,
- readbufferproc, getbufferproc, releasebufferproc, ssizessizeobjargproc)
-from pypy.module.cpyext.pyobject import make_ref, decref, as_pyobj, from_ref
+ readbufferproc, getbufferproc, ssizessizeobjargproc)
+from pypy.module.cpyext.pyobject import make_ref, decref, from_ref
from pypy.module.cpyext.pyerrors import PyErr_Occurred
from pypy.module.cpyext.memoryobject import fill_Py_buffer
from pypy.module.cpyext.state import State
from pypy.module.cpyext import userslot
-from pypy.interpreter.buffer import BufferView
+from pypy.module.cpyext.buffer import CBuffer, CPyBuffer, fq
from pypy.interpreter.error import OperationError, oefmt
from pypy.interpreter.argument import Arguments
-from rpython.rlib.buffer import RawBuffer
from rpython.rlib.unroll import unrolling_iterable
from rpython.rlib.objectmodel import specialize, not_rpython
from rpython.tool.sourcetools import func_renamer
from rpython.flowspace.model import Constant
from rpython.flowspace.specialcase import register_flow_sc
-from rpython.rtyper.annlowlevel import llhelper
from pypy.module.sys.version import CPYTHON_VERSION
PY3 = CPYTHON_VERSION[0] == 3
@@ -324,141 +321,6 @@
space.fromcache(State).check_and_raise_exception(always=True)
return space.newint(res)
-class CPyBuffer(BufferView):
- # Similar to Py_buffer
- _immutable_ = True
-
- def __init__(self, space, ptr, size, w_obj, format='B', shape=None,
- strides=None, ndim=1, itemsize=1, readonly=True,
- needs_decref=False,
- releasebufferproc=rffi.cast(rffi.VOIDP, 0)):
- self.space = space
- self.ptr = ptr
- self.size = size
- self.w_obj = w_obj # kept alive
- self.pyobj = as_pyobj(space, w_obj)
- self.format = format
- self.ndim = ndim
- self.itemsize = itemsize
-
- if not shape:
- self.shape = [size]
- else:
- self.shape = shape
- if not strides:
- self.strides = [1]
- else:
- self.strides = strides
- self.readonly = readonly
- self.needs_decref = needs_decref
- self.releasebufferproc = releasebufferproc
-
- def releasebuffer(self):
- if self.pyobj:
- if self.needs_decref:
- if self.releasebufferproc:
- func_target = rffi.cast(releasebufferproc,
self.releasebufferproc)
- with lltype.scoped_alloc(Py_buffer) as pybuf:
- pybuf.c_buf = self.ptr
- pybuf.c_len = self.size
- pybuf.c_ndim = cts.cast('int', self.ndim)
- pybuf.c_shape = cts.cast('Py_ssize_t*', pybuf.c__shape)
- pybuf.c_strides = cts.cast('Py_ssize_t*',
pybuf.c__strides)
- for i in range(self.ndim):
- pybuf.c_shape[i] = self.shape[i]
- pybuf.c_strides[i] = self.strides[i]
- if self.format:
- pybuf.c_format = rffi.str2charp(self.format)
- else:
- pybuf.c_format = rffi.str2charp("B")
- generic_cpy_call(self.space, func_target, self.pyobj,
pybuf)
- decref(self.space, self.pyobj)
- self.pyobj = lltype.nullptr(PyObject.TO)
- else:
- #do not call twice
- return
-
- def getlength(self):
- return self.size
-
- def getbytes(self, start, size):
- return ''.join([self.ptr[i] for i in range(start, start + size)])
-
- def setbytes(self, start, string):
- # absolutely no safety checks, what could go wrong?
- for i in range(len(string)):
- self.ptr[start + i] = string[i]
-
- def as_str(self):
- return CBuffer(self).as_str()
-
- def as_readbuf(self):
- return CBuffer(self)
-
- def as_writebuf(self):
- assert not self.readonly
- return CBuffer(self)
-
- def get_raw_address(self):
- return rffi.cast(rffi.CCHARP, self.ptr)
-
- def getformat(self):
- return self.format
-
- def getshape(self):
- return self.shape
-
- def getstrides(self):
- return self.strides
-
- def getitemsize(self):
- return self.itemsize
-
- def getndim(self):
- return self.ndim
-
-class FQ(rgc.FinalizerQueue):
- Class = CPyBuffer
- def finalizer_trigger(self):
- while 1:
- buf = self.next_dead()
- if not buf:
- break
- buf.releasebuffer()
-
-fq = FQ()
-
-
-class CBuffer(RawBuffer):
- _immutable_ = True
- def __init__(self, view):
- self.view = view
- self.readonly = view.readonly
-
- def getlength(self):
- return self.view.getlength()
-
- def getitem(self, index):
- return self.view.ptr[index]
-
- def getslice(self, start, stop, step, size):
- assert step == 1
- assert stop - start == size
- ptr = rffi.ptradd(cts.cast('char *', self.view.ptr), start)
- return rffi.charpsize2str(ptr, size)
-
- def setitem(self, index, char):
- self.view.ptr[index] = char
-
- def setslice(self, index, s):
- assert s is not None
- ptr = rffi.ptradd(cts.cast('char *', self.view.ptr), index)
- rffi.str2chararray(s, ptr, len(s))
-
- def get_raw_address(self):
- return cts.cast('char *', self.view.ptr)
-
-
def wrap_getreadbuffer(space, w_self, w_args, func):
func_target = rffi.cast(readbufferproc, func)
py_obj = make_ref(space, w_self)
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
@@ -11,7 +11,7 @@
_PyString_Join)
from pypy.module.cpyext.api import PyObjectP, PyObject, Py_ssize_tP,
generic_cpy_call
from pypy.module.cpyext.pyobject import Py_DecRef, from_ref, make_ref
-from pypy.module.cpyext.object import PyObject_AsCharBuffer
+from pypy.module.cpyext.buffer import PyObject_AsCharBuffer
from pypy.module.cpyext.api import PyTypeObjectPtr
diff --git a/pypy/module/cpyext/test/test_typeobject.py
b/pypy/module/cpyext/test/test_typeobject.py
--- a/pypy/module/cpyext/test/test_typeobject.py
+++ b/pypy/module/cpyext/test/test_typeobject.py
@@ -1425,3 +1425,31 @@
module.add_doc_string_method(a.foo_43)
assert a.foo_43.__doc__ == "A docstring"
+class AppTestHashable(AppTestCpythonExtensionBase):
+ def test_unhashable(self):
+ if not self.runappdirect:
+ skip('pointer to function equality available'
+ ' only after translation')
+ module = self.import_extension('foo', [
+ ("new_obj", "METH_NOARGS",
+ '''
+ PyObject *obj;
+ obj = PyObject_New(PyObject, &Foo_Type);
+ return obj;
+ '''
+ )], prologue='''
+ static PyTypeObject Foo_Type = {
+ PyVarObject_HEAD_INIT(NULL, 0)
+ "foo.foo",
+ };
+ ''', more_init = '''
+ Foo_Type.tp_flags = Py_TPFLAGS_DEFAULT;
+ Foo_Type.tp_hash = PyObject_HashNotImplemented;
+ if (PyType_Ready(&Foo_Type) < 0) INITERROR;
+ ''')
+ obj = module.new_obj()
+ raises(TypeError, hash, obj)
+ assert type(obj).__dict__['__hash__'] is None
+ # this is equivalent to
+ from collections import Hashable
+ assert not isinstance(obj, Hashable)
diff --git a/pypy/module/cpyext/typeobject.py b/pypy/module/cpyext/typeobject.py
--- a/pypy/module/cpyext/typeobject.py
+++ b/pypy/module/cpyext/typeobject.py
@@ -345,13 +345,19 @@
setattr(struct, slot_names[1], slot_func_helper)
def add_operators(space, dict_w, pto):
- # XXX support PyObject_HashNotImplemented
+ from pypy.module.cpyext.object import PyObject_HashNotImplemented
+ hash_not_impl = PyObject_HashNotImplemented.api_func.get_llhelper(space)
for method_name, slot_names, wrapper_func, wrapper_func_kwds, doc in
slotdefs_for_wrappers:
if method_name in dict_w:
continue
offset = [rffi.offsetof(lltype.typeOf(pto).TO, slot_names[0])]
if len(slot_names) == 1:
func = getattr(pto, slot_names[0])
+ if slot_names[0] == 'c_tp_hash':
+ if hash_not_impl == func:
+ # special case for tp_hash == PyObject_HashNotImplemented
+ dict_w[method_name] = space.w_None
+ continue
else:
assert len(slot_names) == 2
struct = getattr(pto, slot_names[0])
diff --git a/rpython/rlib/rvmprof/cintf.py b/rpython/rlib/rvmprof/cintf.py
--- a/rpython/rlib/rvmprof/cintf.py
+++ b/rpython/rlib/rvmprof/cintf.py
@@ -58,6 +58,7 @@
SHARED.join('compat.c'),
SHARED.join('machine.c'),
SHARED.join('vmp_stack.c'),
+ SHARED.join('vmprof_main.c'),
# symbol table already in separate_module_files
] + separate_module_files,
post_include_bits=[],
diff --git a/rpython/rlib/rvmprof/src/shared/vmprof_main.c
b/rpython/rlib/rvmprof/src/shared/vmprof_main.c
new file mode 100644
--- /dev/null
+++ b/rpython/rlib/rvmprof/src/shared/vmprof_main.c
@@ -0,0 +1,30 @@
+#ifdef VMPROF_UNIX
+
+#include <unistd.h>
+/* value: LSB bit is 1 if signals must be ignored; all other bits
+ are a counter for how many threads are currently in a signal handler */
+static long volatile signal_handler_value = 1;
+
+void vmprof_ignore_signals(int ignored)
+{
+ if (!ignored) {
+ __sync_fetch_and_and(&signal_handler_value, ~1L);
+ } else {
+ /* set the last bit, and wait until concurrently-running signal
+ handlers finish */
+ while (__sync_or_and_fetch(&signal_handler_value, 1L) != 1L) {
+ usleep(1);
+ }
+ }
+}
+
+long vmprof_enter_signal(void)
+{
+ return __sync_fetch_and_add(&signal_handler_value, 2L);
+}
+
+long vmprof_exit_signal(void)
+{
+ return __sync_sub_and_fetch(&signal_handler_value, 2L);
+}
+#endif
diff --git a/rpython/rlib/rvmprof/src/shared/vmprof_main.h
b/rpython/rlib/rvmprof/src/shared/vmprof_main.h
--- a/rpython/rlib/rvmprof/src/shared/vmprof_main.h
+++ b/rpython/rlib/rvmprof/src/shared/vmprof_main.h
@@ -60,25 +60,9 @@
/************************************************************/
-/* value: last bit is 1 if signals must be ignored; all other bits
- are a counter for how many threads are currently in a signal handler */
-static long volatile signal_handler_value = 1;
-
-RPY_EXTERN
-void vmprof_ignore_signals(int ignored)
-{
- if (!ignored) {
- __sync_fetch_and_and(&signal_handler_value, ~1L);
- }
- else {
- /* set the last bit, and wait until concurrently-running signal
- handlers finish */
- while (__sync_or_and_fetch(&signal_handler_value, 1L) != 1L) {
- usleep(1);
- }
- }
-}
-
+RPY_EXTERN void vmprof_ignore_signals(int ignored);
+RPY_EXTERN long vmprof_enter_signal(void);
+RPY_EXTERN long vmprof_exit_signal(void);
/* *************************************************************
* functions to write a profile file compatible with gperftools
@@ -276,7 +260,7 @@
__sync_lock_release(&spinlock);
#endif
- long val = __sync_fetch_and_add(&signal_handler_value, 2L);
+ long val = vmprof_enter_signal();
if ((val & 1) == 0) {
int saved_errno = errno;
@@ -307,7 +291,7 @@
errno = saved_errno;
}
- __sync_sub_and_fetch(&signal_handler_value, 2L);
+ vmprof_exit_signal();
}
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit