def _rawrefcount_perform(space): from pypy.module.cpyext.pyobject import PyObject, decref while True: py_obj = rawrefcount.next_dead(PyObject) if not py_obj: break decref(space, py_obj)
def test_iterkeys(self, space): w_dict = space.sys.getdict(space) py_dict = make_ref(space, w_dict) ppos = lltype.malloc(Py_ssize_tP.TO, 1, flavor='raw') pkey = lltype.malloc(PyObjectP.TO, 1, flavor='raw') pvalue = lltype.malloc(PyObjectP.TO, 1, flavor='raw') keys_w = [] values_w = [] try: ppos[0] = 0 while PyDict_Next(space, w_dict, ppos, pkey, None): w_key = from_ref(space, pkey[0]) keys_w.append(w_key) ppos[0] = 0 while PyDict_Next(space, w_dict, ppos, None, pvalue): w_value = from_ref(space, pvalue[0]) values_w.append(w_value) finally: lltype.free(ppos, flavor='raw') lltype.free(pkey, flavor='raw') lltype.free(pvalue, flavor='raw') decref(space, py_dict) # release borrowed references assert space.eq_w(space.newlist(keys_w), space.call_method(w_dict, "keys")) assert space.eq_w(space.newlist(values_w), space.call_method(w_dict, "values"))
def inherit_slots(space, pto, w_base): base_pyo = make_ref(space, w_base) try: base = rffi.cast(PyTypeObjectPtr, base_pyo) if not pto.c_tp_dealloc: pto.c_tp_dealloc = base.c_tp_dealloc if not pto.c_tp_init: pto.c_tp_init = base.c_tp_init if not pto.c_tp_alloc: pto.c_tp_alloc = base.c_tp_alloc # XXX check for correct GC flags! if not pto.c_tp_free: pto.c_tp_free = base.c_tp_free if not pto.c_tp_setattro: pto.c_tp_setattro = base.c_tp_setattro if not pto.c_tp_getattro: pto.c_tp_getattro = base.c_tp_getattro if not pto.c_tp_as_buffer: pto.c_tp_as_buffer = base.c_tp_as_buffer if base.c_tp_as_buffer: # inherit base.c_tp_as_buffer functions not inherited from w_type pto_as = pto.c_tp_as_buffer base_as = base.c_tp_as_buffer if not pto_as.c_bf_getbuffer: pto_as.c_bf_getbuffer = base_as.c_bf_getbuffer if not pto_as.c_bf_releasebuffer: pto_as.c_bf_releasebuffer = base_as.c_bf_releasebuffer finally: decref(space, base_pyo)
def PyBytes_ConcatAndDel(space, ref, newpart): """Create a new string object in *string containing the contents of newpart appended to string. This version decrements the reference count of newpart.""" try: PyBytes_Concat(space, ref, newpart) finally: decref(space, newpart)
def type_alloc(typedescr, space, w_metatype, itemsize=0): metatype = rffi.cast(PyTypeObjectPtr, make_ref(space, w_metatype)) # Don't increase refcount for non-heaptypes if metatype: flags = rffi.cast(lltype.Signed, metatype.c_tp_flags) if not flags & Py_TPFLAGS_HEAPTYPE: decref(space, metatype) heaptype = lltype.malloc(PyHeapTypeObject.TO, flavor='raw', zero=True, add_memory_pressure=True) pto = heaptype.c_ht_type pto.c_ob_refcnt = 1 pto.c_ob_pypy_link = 0 pto.c_ob_type = metatype pto.c_tp_flags |= Py_TPFLAGS_HEAPTYPE pto.c_tp_as_number = heaptype.c_as_number pto.c_tp_as_sequence = heaptype.c_as_sequence pto.c_tp_as_mapping = heaptype.c_as_mapping pto.c_tp_as_buffer = heaptype.c_as_buffer pto.c_tp_basicsize = -1 # hopefully this makes malloc bail out pto.c_tp_itemsize = 0 return rffi.cast(PyObject, heaptype)
def _PyBytes_Resize(space, ref, newsize): """A way to resize a string object even though it is "immutable". Only use this to build up a brand new string object; don't use this if the string may already be known in other parts of the code. It is an error to call this function if the refcount on the input string object is not one. Pass the address of an existing string object as an lvalue (it may be written into), and the new size desired. On success, *string holds the resized string object and 0 is returned; the address in *string may differ from its input value. If the reallocation fails, the original string object at *string is deallocated, *string is set to NULL, a memory exception is set, and -1 is returned. """ # XXX always create a new string so far if pyobj_has_w_obj(ref[0]): raise oefmt(space.w_SystemError, "_PyBytes_Resize called on already created string") py_str = rffi.cast(PyBytesObject, ref[0]) try: py_newstr = new_empty_str(space, newsize) except MemoryError: decref(space, ref[0]) ref[0] = lltype.nullptr(PyObject.TO) raise to_cp = newsize oldsize = py_str.c_ob_size if oldsize < newsize: to_cp = oldsize for i in range(to_cp): py_newstr.c_ob_sval[i] = py_str.c_ob_sval[i] decref(space, ref[0]) ref[0] = rffi.cast(PyObject, py_newstr) return 0
def releasebuffer(self): if self.pyobj: if self.needs_decref: if self.releasebufferproc: func_target = rffi.cast(releasebufferproc, self.releasebufferproc) size = rffi.sizeof(cts.gettype('Py_buffer')) pybuf = lltype.malloc(rffi.VOIDP.TO, size, flavor='raw', zero=True) pybuf = cts.cast('Py_buffer*', 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] fmt = rffi.str2charp(self.format if self.format else "B") try: pybuf.c_format = fmt generic_cpy_call(self.space, func_target, self.pyobj, pybuf) finally: lltype.free(fmt, flavor='raw') lltype.free(pybuf, flavor='raw') decref(self.space, self.pyobj) self.pyobj = lltype.nullptr(PyObject.TO) self.w_obj = None else: #do not call twice return
def finish_type_2(space, pto, w_obj): """ Sets up other attributes, when the interpreter type has been created. """ pto.c_tp_mro = make_ref(space, space.newtuple(w_obj.mro_w)) base = pto.c_tp_base if base: inherit_special(space, pto, w_obj, base) for w_base in space.fixedview(from_ref(space, pto.c_tp_bases)): if isinstance(w_base, W_TypeObject): inherit_slots(space, pto, w_base) #else: # w_base is a W_ClassObject, ignore it if not pto.c_tp_setattro: from pypy.module.cpyext.object import PyObject_GenericSetAttr pto.c_tp_setattro = llslot(space, PyObject_GenericSetAttr) if not pto.c_tp_getattro: from pypy.module.cpyext.object import PyObject_GenericGetAttr pto.c_tp_getattro = llslot(space, PyObject_GenericGetAttr) if w_obj.is_cpytype(): decref(space, pto.c_tp_dict) w_dict = w_obj.getdict(space) # pass in the w_obj to convert any values that are # unbound GetSetProperty into bound PyGetSetDescrObject pto.c_tp_dict = make_ref(space, w_dict, w_obj)
def _PyTuple_Resize(space, p_ref, newsize): """Can be used to resize a tuple. newsize will be the new length of the tuple. Because tuples are supposed to be immutable, this should only be used if there is only one reference to the object. Do not use this if the tuple may already be known to some other part of the code. The tuple will always grow or shrink at the end. Think of this as destroying the old tuple and creating a new one, only more efficiently. Returns 0 on success. Client code should never assume that the resulting value of *p will be the same as before calling this function. If the object referenced by *p is replaced, the original *p is destroyed. On failure, returns -1 and sets *p to NULL, and raises MemoryError or SystemError.""" ref = p_ref[0] if not tuple_check_ref(space, ref): PyErr_BadInternalCall(space) oldref = rffi.cast(PyTupleObject, ref) oldsize = oldref.c_ob_size p_ref[0] = new_empty_tuple(space, newsize) newref = rffi.cast(PyTupleObject, p_ref[0]) try: if oldsize < newsize: to_cp = oldsize else: to_cp = newsize for i in range(to_cp): ob = oldref.c_ob_item[i] incref(space, ob) newref.c_ob_item[i] = ob except: decref(space, p_ref[0]) p_ref[0] = lltype.nullptr(PyObject.TO) raise finally: decref(space, ref) return 0
def _PySet_NextEntry(space, w_set, ppos, pkey, phash): if w_set is None or not PyAnySet_Check(space, w_set): PyErr_BadInternalCall(space) return -1 if not pkey: PyErr_BadInternalCall(space) return -1 pos = ppos[0] py_obj = as_pyobj(space, w_set) py_set = rffi.cast(PySetObject, py_obj) if pos == 0: # Store the current item list in the PySetObject. # w_keys must use the object strategy in order to keep the keys alive w_keys = space.newlist(space.listview(w_set)) w_keys.switch_to_object_strategy() oldlist = py_set.c__tmplist py_set.c__tmplist = create_ref(space, w_keys) incref(space, py_set.c__tmplist) decref(space, oldlist) else: if not py_set.c__tmplist: # pos should have been 0, cannot fail so return 0 return 0 w_keys = from_ref(space, py_set.c__tmplist) ppos[0] += 1 if pos >= space.len_w(w_keys): decref(space, py_set.c__tmplist) py_set.c__tmplist = lltype.nullptr(PyObject.TO) return 0 w_key = space.listview(w_keys)[pos] pkey[0] = as_pyobj(space, w_key) if phash: phash[0] = space.hash_w(w_key) return 1
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 tuple_attach(space, py_obj, w_obj, w_userdata=None): """ Fills a newly allocated PyTupleObject with the given tuple object. The buffer must not be modified. """ items_w = space.fixedview(w_obj) py_tup = rffi.cast(PyTupleObject, py_obj) length = len(items_w) if py_tup.c_ob_size < length: raise oefmt( space.w_ValueError, "tuple_attach called on object with ob_size %d but trying to store %d", py_tup.c_ob_size, length) i = 0 try: while i < length: py_tup.c_ob_item[i] = make_ref(space, items_w[i]) i += 1 except: while i > 0: i -= 1 ob = py_tup.c_ob_item[i] py_tup.c_ob_item[i] = lltype.nullptr(PyObject.TO) decref(space, ob) raise
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_getbuffer): raise oefmt(space.w_TypeError, "expected an object with the buffer interface") with lltype.scoped_alloc(Py_buffer) as view: ret = generic_cpy_call(space, pb.c_bf_getbuffer, obj, view, rffi.cast(rffi.INT_real, PyBUF_SIMPLE)) if rffi.cast(lltype.Signed, ret) == -1: return -1 bufferp[0] = rffi.cast(rffi.CCHARP, view.c_buf) sizep[0] = view.c_len if pb.c_bf_releasebuffer: generic_cpy_call(space, pb.c_bf_releasebuffer, obj, view) decref(space, view.c_obj) return 0
def wrap_result(self, space, lresult): space.getbuiltinmodule("cpyext") from pypy.module.cpyext.pyobject import PyObject, from_ref, make_ref, decref result = rffi.cast(PyObject, lresult) w_obj = from_ref(space, result) if result: decref(space, result) return w_obj
def unicode_dealloc(space, py_obj): py_unicode = rffi.cast(PyUnicodeObject, py_obj) decref(space, py_unicode.c_defenc) if py_unicode.c_str: lltype.free(py_unicode.c_str, flavor="raw") from pypy.module.cpyext.object import _dealloc _dealloc(space, py_obj)
def buffer_dealloc(space, py_obj): py_buf = rffi.cast(PyBufferObject, py_obj) if py_buf.c_b_base: decref(space, py_buf.c_b_base) else: rffi.free_charp(rffi.cast(rffi.CCHARP, py_buf.c_b_ptr)) from pypy.module.cpyext.object import _dealloc _dealloc(space, py_obj)
def perform(self, executioncontext, frame): from pypy.module.cpyext.pyobject import PyObject, decref while True: py_obj = rawrefcount.next_dead(PyObject) if not py_obj: break decref(self.space, py_obj)
def call(self, space, w_self, __args__): func = self.get_func_to_call() func_target = rffi.cast(ternaryfunc, func) py_args = tuple_from_args_w(space, __args__.arguments_w) w_kwargs = w_kwargs_from_args(space, __args__) ret = generic_cpy_call(space, func_target, w_self, py_args, w_kwargs) decref(space, py_args) return ret
def call_keywords(self, space, w_self, __args__): func = rffi.cast(PyCFunctionKwArgs, self.ml.c_ml_meth) py_args = tuple_from_args_w(space, __args__.arguments_w) w_kwargs = w_kwargs_from_args(space, __args__) try: return generic_cpy_call(space, func, w_self, py_args, w_kwargs) finally: decref(space, py_args)
def call_varargs(self, space, w_self, __args__): state = space.fromcache(State) func = self.ml.c_ml_meth py_args = tuple_from_args_w(space, __args__.arguments_w) try: return generic_cpy_call(space, func, w_self, py_args) finally: decref(space, py_args)
def _dealloc(space, obj): # This frees an object after its refcount dropped to zero, so we # assert that it is really zero here. assert obj.c_ob_refcnt == 0 pto = obj.c_ob_type obj_voidp = rffi.cast(rffi.VOIDP, obj) generic_cpy_call(space, pto.c_tp_free, obj_voidp) if pto.c_tp_flags & Py_TPFLAGS_HEAPTYPE: decref(space, rffi.cast(PyObject, pto))
def test_freelist_direct(self, space): state = space.fromcache(State) p_x = state.C.PyInt_FromLong(12345678) decref(space, p_x) p_y = state.C.PyInt_FromLong(87654321) # check that the address is the same, i.e. that the freelist did its # job assert p_x == p_y decref(space, p_y)
def get_flags(signature, body="pass"): w_code = space.appexec([], """(): def func(%s): %s return func.__code__ """ % (signature, body)) ref = make_ref(space, w_code) co_flags = rffi.cast(PyCodeObject, ref).c_co_flags decref(space, ref) return co_flags
def member_setter(self, space, w_self, w_value): assert isinstance(self, W_MemberDescr) check_descr(space, w_self, self.w_type) pyref = make_ref(space, w_self) try: PyMember_SetOne(space, rffi.cast(rffi.CCHARP, pyref), self.member, w_value) finally: decref(space, pyref)
def tuple_dealloc(space, py_obj): """Frees allocated PyTupleObject resources. """ py_tup = rffi.cast(PyTupleObject, py_obj) p = py_tup.c_ob_item for i in range(py_tup.c_ob_size): decref(space, p[i]) from pypy.module.cpyext.object import _dealloc _dealloc(space, py_obj)
def test_fromstring(self, space): s = rffi.str2charp(u'sp\x09m'.encode("utf-8")) w_res = PyUnicode_FromString(space, s) assert space.unicode_w(w_res) == u'sp\x09m' res = PyUnicode_FromStringAndSize(space, s, 4) w_res = from_ref(space, res) decref(space, res) assert space.unicode_w(w_res) == u'sp\x09m' rffi.free_charp(s)
def _str_getreadbuffer(space, w_str, segment, ref): from pypy.module.cpyext.bytesobject import PyString_AsString if segment != 0: raise oefmt(space.w_SystemError, "accessing non-existent string segment") pyref = make_ref(space, w_str) ref[0] = PyString_AsString(space, pyref) # Stolen reference: the object has better exist somewhere else decref(space, pyref) return space.len_w(w_str)
def call(self, space, w_self, __args__): func = self.get_func_to_call() func_init = rffi.cast(initproc, func) py_args = tuple_from_args_w(space, __args__.arguments_w) w_kwargs = w_kwargs_from_args(space, __args__) res = generic_cpy_call(space, func_init, w_self, py_args, w_kwargs) decref(space, py_args) if rffi.cast(lltype.Signed, res) == -1: space.fromcache(State).check_and_raise_exception(always=True) return None
def wrap_binaryfunc_l(space, w_self, w_args, func): func_binary = rffi.cast(binaryfunc, func) check_num_args(space, w_args, 1) args_w = space.fixedview(w_args) ref = make_ref(space, w_self) if (not ref.c_ob_type.c_tp_flags & Py_TPFLAGS_CHECKTYPES and not space.issubtype_w(space.type(args_w[0]), space.type(w_self))): return space.w_NotImplemented decref(space, ref) return generic_cpy_call(space, func_binary, w_self, args_w[0])
def PyThreadState_Clear(space, tstate): """Reset all information in a thread state object. The global interpreter lock must be held.""" if not space.config.translation.thread: raise NoThreads decref(space, tstate.c_dict) tstate.c_dict = lltype.nullptr(PyObject.TO) space.threadlocals.leave_thread(space) space.getexecutioncontext().cleanup_cpyext_state() rthread.gc_thread_die()
def tuple_dealloc(space, py_obj): """Frees allocated PyTupleObject resources. """ py_tup = rffi.cast(PyTupleObject, py_obj) p = py_tup.c_ob_item if p: for i in range(py_tup.c_ob_size): decref(space, p[i]) lltype.free(p, flavor="raw") from pypy.module.cpyext.object import PyObject_dealloc PyObject_dealloc(space, py_obj)
def PyTuple_SetItem(space, ref, index, py_obj): # XXX this will not complain when changing tuples that have # already been realized as a W_TupleObject, but won't update the # W_TupleObject if not tuple_check_ref(space, ref): decref(space, py_obj) PyErr_BadInternalCall(space) ref = rffi.cast(PyTupleObject, ref) size = ref.c_ob_size if index < 0 or index >= size: raise OperationError(space.w_IndexError, space.wrap("tuple assignment index out of range")) old_ref = ref.c_ob_item[index] ref.c_ob_item[index] = py_obj # consumes a reference if old_ref: decref(space, old_ref) return 0
def tuple_attach(space, py_obj, w_obj): """ Fills a newly allocated PyTupleObject with the given tuple object. The buffer must not be modified. """ items_w = space.fixedview(w_obj) l = len(items_w) p = lltype.malloc(ObjectItems, l, flavor='raw') i = 0 try: while i < l: p[i] = make_ref(space, items_w[i]) i += 1 except: while i > 0: i -= 1 decref(space, p[i]) lltype.free(p, flavor='raw') raise py_tup = rffi.cast(PyTupleObject, py_obj) py_tup.c_ob_size = l py_tup.c_ob_item = p
def tuple_attach(space, py_obj, w_obj): """ Fills a newly allocated PyTupleObject with the given tuple object. The buffer must not be modified. """ items_w = space.fixedview(w_obj) py_tup = rffi.cast(PyTupleObject, py_obj) length = len(items_w) if py_tup.c_ob_size < length: raise oefmt(space.w_ValueError, "tuple_attach called on object with ob_size %d but trying to store %d", py_tup.c_ob_size, length) i = 0 try: while i < length: py_tup.c_ob_item[i] = make_ref(space, items_w[i]) i += 1 except: while i > 0: i -= 1 ob = py_tup.c_ob_item[i] py_tup.c_ob_item[i] = lltype.nullptr(PyObject.TO) decref(space, ob) raise
def setitem(self, w_list, index, w_obj): storage = self.unerase(w_list.lstorage) index = self._check_index(index, storage._length) decref(w_list.space, storage._elems[index]) storage._elems[index] = make_ref(w_list.space, w_obj)
def __del__(self): for i in range(self._length): decref(self.space, self._elems[i]) lltype.free(self._elems, flavor='raw')