def test_callback(self): slong = cast_type_to_ffitype(rffi.LONG) libc = self.get_libc() qsort = libc.getpointer("qsort", [ffi_type_pointer, slong, slong, ffi_type_pointer], ffi_type_void) def callback(ll_args, ll_res, stuff): p_a1 = rffi.cast(rffi.VOIDPP, ll_args[0])[0] p_a2 = rffi.cast(rffi.VOIDPP, ll_args[1])[0] a1 = rffi.cast(rffi.INTP, p_a1)[0] a2 = rffi.cast(rffi.INTP, p_a2)[0] res = rffi.cast(rffi.SIGNEDP, ll_res) # must store a full ffi arg! if a1 > a2: res[0] = 1 else: res[0] = -1 ptr = CallbackFuncPtr([ffi_type_pointer, ffi_type_pointer], ffi_type_sint, callback) TP = rffi.CArray(rffi.INT) to_sort = lltype.malloc(TP, 4, flavor="raw") to_sort[0] = rffi.cast(rffi.INT, 4) to_sort[1] = rffi.cast(rffi.INT, 3) to_sort[2] = rffi.cast(rffi.INT, 1) to_sort[3] = rffi.cast(rffi.INT, 2) qsort.push_arg(rffi.cast(rffi.VOIDP, to_sort)) qsort.push_arg(rffi.sizeof(rffi.INT)) qsort.push_arg(4) qsort.push_arg(ptr.ll_closure) qsort.call(lltype.Void) assert [rffi.cast(lltype.Signed, to_sort[i]) for i in range(4)] == [1, 2, 3, 4] lltype.free(to_sort, flavor="raw") keepalive_until_here(ptr) # <= this test is not translated, but don't
def copy_string_contents(src, dst, srcstart, dststart, length): """Copies 'length' characters from the 'src' string to the 'dst' string, starting at position 'srcstart' and 'dststart'.""" # xxx Warning: don't try to do this at home. It relies on a lot # of details to be sure that it works correctly in all cases. # Notably: no GC operation at all from the first cast_ptr_to_adr() # because it might move the strings. The keepalive_until_here() # are obscurely essential to make sure that the strings stay alive # longer than the raw_memcopy(). assert length >= 0 ll_assert(srcstart >= 0, "copystrc: negative srcstart") ll_assert(srcstart + length <= len(src.chars), "copystrc: src ovf") ll_assert(dststart >= 0, "copystrc: negative dststart") ll_assert(dststart + length <= len(dst.chars), "copystrc: dst ovf") # # If the 'split_gc_address_space' option is set, we must copy # manually, character-by-character if rgc.must_split_gc_address_space(): i = 0 while i < length: dst.chars[dststart + i] = src.chars[srcstart + i] i += 1 return # # # from here, no GC operations can happen asrc = _get_raw_buf(SRC_TP, src, srcstart) adst = _get_raw_buf(DST_TP, dst, dststart) llmemory.raw_memcopy(asrc, adst, llmemory.sizeof(CHAR_TP) * length) # end of "no GC" section keepalive_until_here(src) keepalive_until_here(dst)
def _invoke(self, args): arity = len(args) tp_arity = len(self._c_fn_type._arg_types) if self._c_fn_type._is_variadic: if arity < tp_arity: runtime_error(u"Wrong number of args to fn: got " + unicode(str(arity)) + u", expected at least " + unicode(str(tp_arity))) else: if arity != tp_arity: runtime_error(u"Wrong number of args to fn: got " + unicode(str(arity)) + u", expected " + unicode(str(tp_arity))) exb, tokens = self.prep_exb(args) cd = jit.promote(self._c_fn_type.get_cd()) #fp = jit.promote(self._f_ptr) jit_ffi_call(cd, self._f_ptr, exb) ret_val = self.get_ret_val_from_buffer(exb) for x in range(len(args)): t = tokens[x] if t is not None: t.finalize_token() lltype.free(exb, flavor="raw") keepalive_until_here(args) return ret_val
def _do_setslice(self, w_slice, w_value): ctptr, start, length = self._do_getslicearg(w_slice) ctitem = ctptr.ctitem ctitemsize = ctitem.size cdata = rffi.ptradd(self._cdata, start * ctitemsize) # if isinstance(w_value, W_CData): from pypy.module._cffi_backend import ctypearray ctv = w_value.ctype if (isinstance(ctv, ctypearray.W_CTypeArray) and ctv.ctitem is ctitem and w_value.get_array_length() == length): # fast path: copying from exactly the correct type s = w_value._cdata for i in range(ctitemsize * length): cdata[i] = s[i] keepalive_until_here(w_value) return # space = self.space w_iter = space.iter(w_value) for i in range(length): try: w_item = space.next(w_iter) except OperationError, e: if not e.match(space, space.w_StopIteration): raise raise operationerrfmt(space.w_ValueError, "need %d values to unpack, got %d", length, i) ctitem.convert_from_object(cdata, w_item) cdata = rffi.ptradd(cdata, ctitemsize)
def w_getitem(self, space, idx): item = self.get_buffer()[idx] keepalive_until_here(self) if mytype.typecode in 'bBhHil': item = rffi.cast(lltype.Signed, item) return space.newint(item) if mytype.typecode in 'IL': return space.newint(item) elif mytype.typecode in 'fd': item = float(item) return space.newfloat(item) elif mytype.typecode == 'c': return space.newbytes(item) elif mytype.typecode == 'u': code = r_uint(ord(item)) # cpython will allow values > sys.maxunicode # while silently truncating the top bits if code <= r_uint(0x7F): # Encode ASCII item = chr(code) elif code <= r_uint(0x07FF): item = (chr((0xc0 | (code >> 6))) + chr((0x80 | (code & 0x3f)))) elif code <= r_uint(0xFFFF): item = (chr((0xe0 | (code >> 12))) + chr((0x80 | ((code >> 6) & 0x3f))) + chr((0x80 | (code & 0x3f)))) else: item = (chr((0xf0 | (code >> 18)) & 0xff) + chr((0x80 | ((code >> 12) & 0x3f))) + chr((0x80 | ((code >> 6) & 0x3f))) + chr((0x80 | (code & 0x3f)))) return space.newutf8(item, 1) assert 0, "unreachable"
def _copy_from_same(self, cdata, w_ob): if isinstance(w_ob, cdataobj.W_CData): if w_ob.ctype is self and self.size >= 0: misc._raw_memcopy(w_ob._cdata, cdata, self.size) keepalive_until_here(w_ob) return True return False
def main(argv): glob.ping = False lst1 = [X() for i in range(256)] lst = [X() for i in range(3000)] for i, x in enumerate(lst): x.baz = i fq.register_finalizer(x) for i in range(3000): lst[i] = None if i % 300 == 150: rgc.collect() revdb.stop_point() j = i + glob.ping * 1000000 assert foobar(j) == j if glob.ping: glob.ping = False total = 0 while True: x = fq.next_dead() if x is None: break total = intmask(total * 3 + x.baz) assert foobar(total) == total keepalive_until_here(lst1) return 9
def main(argv): rawrefcount.create_link_pypy(w1, ob1) w = None ob = lltype.nullptr(PyObjectS) oblist = [] for op in argv[1:]: revdb.stop_point() w = W_Root(42) ob = lltype.malloc(PyObjectS, flavor='raw', zero=True) ob.c_ob_refcnt = rawrefcount.REFCNT_FROM_PYPY rawrefcount.create_link_pypy(w, ob) oblist.append(ob) del oblist[-1] # rgc.collect() assert rawrefcount.from_obj(PyObject, w) == ob assert rawrefcount.to_obj(W_Root, ob) == w while True: ob = rawrefcount.next_dead(PyObject) if not ob: break assert ob in oblist oblist.remove(ob) objectmodel.keepalive_until_here(w) revdb.stop_point() return 9
def main(argv): lst, keepalive = make(argv[0]) expected = ['prebuilt'] + [c for c in argv[0]] dead = [False] * len(lst) for j in range(17000): outp = [] for i in range(len(lst)): v = lst[i]() debug_print(v) if dead[i]: assert v is None elif v is None: outp.append('<DEAD>') dead[i] = True else: outp.append(v.s) assert v.s == expected[i] print ''.join(outp) if (j % 1000) == 999: debug_print('============= COLLECT ===========') rgc.collect() debug_print('------ done', j, '.') assert not dead[0] assert not dead[-1] keepalive_until_here(keepalive) revdb.stop_point() return 9
def PySequence_ITEM(space, w_obj, i): """Return the ith element of o or NULL on failure. Macro form of PySequence_GetItem() but without checking that PySequence_Check(o)() is true and without adjustment for negative indices. This function used an int type for i. This might require changes in your code for properly supporting 64-bit systems.""" # XXX we should call Py*_GET_ITEM() instead of Py*_GetItem() # from here, but we cannot because we are also called from # PySequence_GetItem() py_obj = as_pyobj(space, w_obj) if isinstance(w_obj, tupleobject.W_TupleObject): from pypy.module.cpyext.tupleobject import PyTuple_GetItem py_res = PyTuple_GetItem(space, py_obj, i) incref(space, py_res) keepalive_until_here(w_obj) return py_res if isinstance(w_obj, W_ListObject): from pypy.module.cpyext.listobject import PyList_GetItem py_res = PyList_GetItem(space, py_obj, i) incref(space, py_res) keepalive_until_here(w_obj) return py_res as_sequence = py_obj.c_ob_type.c_tp_as_sequence if not as_sequence or not as_sequence.c_sq_item: raise oefmt(space.w_TypeError, "'%T' object does not support indexing", w_obj) ret = generic_cpy_call(space, as_sequence.c_sq_item, w_obj, i) return make_ref(space, ret)
def copy_and_convert_to_object(self, cdata): space = self.space self.check_complete() ob = cdataobj.W_CDataNewOwning(space, self.size, self) misc._raw_memcopy(cdata, ob._cdata, self.size) keepalive_until_here(ob) return ob
def newp(self, w_init): space = self.space ctitem = self.ctitem datasize = ctitem.size if datasize < 0: raise operationerrfmt(space.w_TypeError, "cannot instantiate ctype '%s' of unknown size", self.name) if self.is_struct_ptr: # 'newp' on a struct-or-union pointer: in this case, we return # a W_CDataPtrToStruct object which has a strong reference # to a W_CDataNewOwning that really contains the structure. cdatastruct = cdataobj.W_CDataNewOwning(space, datasize, ctitem) cdata = cdataobj.W_CDataPtrToStructOrUnion(space, cdatastruct._cdata, self, cdatastruct) else: if self.is_char_or_unichar_ptr_or_array(): datasize *= 2 # forcefully add a null character cdata = cdataobj.W_CDataNewOwning(space, datasize, self) # if not space.is_w(w_init, space.w_None): ctitem.convert_from_object(cdata._cdata, w_init) keepalive_until_here(cdata) return cdata
def string(self, cdataobj, maxlen): space = self.space if isinstance(self.ctitem, ctypeprim.W_CTypePrimitive): cdata = cdataobj._cdata if not cdata: raise operationerrfmt(space.w_RuntimeError, "cannot use string() on %s", space.str_w(cdataobj.repr())) # from pypy.module._cffi_backend import ctypearray length = maxlen if length < 0 and isinstance(self, ctypearray.W_CTypeArray): length = cdataobj.get_array_length() # # pointer to a primitive type of size 1: builds and returns a str if self.ctitem.size == rffi.sizeof(lltype.Char): if length < 0: s = rffi.charp2str(cdata) else: s = rffi.charp2strn(cdata, length) keepalive_until_here(cdataobj) return space.wrap(s) # # pointer to a wchar_t: builds and returns a unicode if self.is_unichar_ptr_or_array(): cdata = rffi.cast(rffi.CWCHARP, cdata) if length < 0: u = rffi.wcharp2unicode(cdata) else: u = rffi.wcharp2unicoden(cdata, length) keepalive_until_here(cdataobj) return space.wrap(u) # return W_CType.string(self, cdataobj, maxlen)
def _copy_from_same(self, cdata, w_ob): if isinstance(w_ob, cdataobj.W_CData): if w_ob.ctype is self and self.size >= 0: misc._raw_memcopy(w_ob._cdata, cdata, self.size) keepalive_until_here(w_ob) return True return False
def _invoke(self, args): arity = len(args) tp_arity = len(self._c_fn_type._arg_types) if self._c_fn_type._is_variadic: if arity < tp_arity: runtime_error(u"Wrong number of args to fn: got " + unicode(str(arity)) + u", expected at least " + unicode(str(tp_arity))) else: if arity != tp_arity: runtime_error(u"Wrong number of args to fn: got " + unicode(str(arity)) + u", expected " + unicode(str(tp_arity))) exb, tokens = self.prep_exb(args) cd = jit.promote(self._c_fn_type.get_cd()) #fp = jit.promote(self._f_ptr) jit_ffi_call(cd, self._f_ptr, exb) ret_val = self.get_ret_val_from_buffer(exb) for x in range(len(args)): t = tokens[x] if t is not None: t.finalize_token() lltype.free(exb, flavor="raw") keepalive_until_here(args) return ret_val
def ll_hash_string_siphash24(ll_s): """Called indirectly from lltypesystem/rstr.py, by redirection from objectmodel.ll_string_hash(). """ from rpython.rlib.rarithmetic import intmask # This function is entirely @rgc.no_collect. length = len(ll_s.chars) if lltype.typeOf(ll_s).TO.chars.OF == lltype.Char: # regular STR addr = rstr._get_raw_buf_string(rstr.STR, ll_s, 0) else: # NOTE: a latin-1 unicode string must have the same hash as the # corresponding byte string. If the unicode is all within # 0-255, then we call _siphash24() with a special argument that # will make it load only one byte for every unicode char. # Note also that we give a # different hash result than CPython on ucs4 platforms, for # unicode strings where CPython uses 2 bytes per character. addr = rstr._get_raw_buf_unicode(rstr.UNICODE, ll_s, 0) SZ = rffi.sizeof(rstr.UNICODE.chars.OF) i = 0 while i < length: if ord(ll_s.chars[i]) > 0xFF: length *= SZ break i += 1 else: x = _siphash24(addr, length, SZ) keepalive_until_here(ll_s) return intmask(x) x = _siphash24(addr, length) keepalive_until_here(ll_s) return intmask(x)
def newp(self, w_init): space = self.space datasize = self.size # if datasize < 0: if (space.isinstance_w(w_init, space.w_list) or space.isinstance_w(w_init, space.w_tuple)): length = space.int_w(space.len(w_init)) elif space.isinstance_w(w_init, space.w_basestring): # from a string, we add the null terminator length = space.int_w(space.len(w_init)) + 1 else: length = space.getindex_w(w_init, space.w_OverflowError) if length < 0: raise OperationError(space.w_ValueError, space.wrap("negative array length")) w_init = space.w_None # try: datasize = ovfcheck(length * self.ctitem.size) except OverflowError: raise OperationError(space.w_OverflowError, space.wrap("array size would overflow a ssize_t")) # cdata = cdataobj.W_CDataNewOwningLength(space, datasize, self, length) # else: cdata = cdataobj.W_CDataNewOwning(space, datasize, self) # if not space.is_w(w_init, space.w_None): self.convert_from_object(cdata._cdata, w_init) keepalive_until_here(cdata) return cdata
def cast(self, w_ob): if isinstance(w_ob, cdataobj.W_CData) and isinstance(w_ob.ctype, W_CTypePrimitiveLongDouble): w_cdata = self.convert_to_object(w_ob._cdata) keepalive_until_here(w_ob) return w_cdata else: return W_CTypePrimitiveFloat.cast(self, w_ob)
def get_pyobj_and_incref(space, w_obj, w_userdata=None, immortal=False): pyobj = as_pyobj(space, w_obj, w_userdata, immortal=immortal) if pyobj: # != NULL assert pyobj.c_ob_refcnt >= rawrefcount.REFCNT_FROM_PYPY pyobj.c_ob_refcnt += 1 keepalive_until_here(w_obj) return pyobj
def ll_hash_string_siphash24(ll_s): """Called indirectly from lltypesystem/rstr.py, by redirection from objectmodel.ll_string_hash(). """ from rpython.rlib.rarithmetic import intmask # This function is entirely @rgc.no_collect. length = len(ll_s.chars) if lltype.typeOf(ll_s).TO.chars.OF == lltype.Char: # regular STR addr = rstr._get_raw_buf_string(rstr.STR, ll_s, 0) else: # NOTE: a latin-1 unicode string must have the same hash as the # corresponding byte string. If the unicode is all within # 0-255, then we need to allocate a byte buffer and copy the # latin-1 encoding in it manually. Note also that we give a # different hash result than CPython on ucs4 platforms, for # unicode strings where CPython uses 2 bytes per character. for i in range(length): if ord(ll_s.chars[i]) > 0xFF: addr = rstr._get_raw_buf_unicode(rstr.UNICODE, ll_s, 0) length *= rffi.sizeof(rstr.UNICODE.chars.OF) break else: p = lltype.malloc(rffi.CCHARP.TO, length, flavor='raw') i = 0 while i < length: p[i] = chr(ord(ll_s.chars[i])) i += 1 x = _siphash24(llmemory.cast_ptr_to_adr(p), length) lltype.free(p, flavor='raw') return intmask(x) x = _siphash24(addr, length) keepalive_until_here(ll_s) return intmask(x)
def setitem_slice(self, space, w_idx, w_item): if not isinstance(w_item, W_Array): raise oefmt(space.w_TypeError, "can only assign to a slice array") start, stop, step, size = self.space.decode_index4(w_idx, self.len) assert step != 0 if w_item.len != size or self is w_item: if start == self.len and step > 0: # we actually want simply extend() self.extend(w_item) else: # XXX this is a giant slow hack w_lst = self.descr_tolist(space) w_item = space.call_method(w_item, 'tolist') space.setitem(w_lst, w_idx, w_item) self.setlen(0) self.fromsequence(w_lst) else: buf = self.get_buffer() srcbuf = w_item.get_buffer() i = start for j in range(size): buf[i] = srcbuf[j] i += step keepalive_until_here(w_item) keepalive_until_here(self)
def newp(self, w_init): from pypy.module._cffi_backend.ctypestruct import W_CTypeStructOrUnion space = self.space ctitem = self.ctitem datasize = ctitem.size if datasize < 0: raise oefmt(space.w_TypeError, "cannot instantiate ctype '%s' of unknown size", self.name) if isinstance(ctitem, W_CTypeStructOrUnion): # 'newp' on a struct-or-union pointer: in this case, we return # a W_CDataPtrToStruct object which has a strong reference # to a W_CDataNewOwning that really contains the structure. # if ctitem.with_var_array and not space.is_w(w_init, space.w_None): datasize = ctitem.convert_struct_from_object( lltype.nullptr(rffi.CCHARP.TO), w_init, datasize) # cdatastruct = cdataobj.W_CDataNewOwning(space, datasize, ctitem) cdata = cdataobj.W_CDataPtrToStructOrUnion(space, cdatastruct._cdata, self, cdatastruct) else: if self.is_char_or_unichar_ptr_or_array(): datasize *= 2 # forcefully add a null character cdata = cdataobj.W_CDataNewOwning(space, datasize, self) # if not space.is_w(w_init, space.w_None): ctitem.convert_from_object(cdata._cdata, w_init) keepalive_until_here(cdata) return cdata
def ll_shrink_array(p, smallerlength): from rpython.rtyper.lltypesystem.lloperation import llop from rpython.rlib.objectmodel import keepalive_until_here if llop.shrink_array(lltype.Bool, p, smallerlength): return p # done by the GC # XXX we assume for now that the type of p is GcStruct containing a # variable array, with no further pointers anywhere, and exactly one # field in the fixed part -- like STR and UNICODE. TP = lltype.typeOf(p).TO newp = lltype.malloc(TP, smallerlength) assert len(TP._names) == 2 field = getattr(p, TP._names[0]) setattr(newp, TP._names[0], field) ARRAY = getattr(TP, TP._arrayfld) offset = llmemory.offsetof(TP, TP._arrayfld) + llmemory.itemoffsetof(ARRAY, 0) source_addr = llmemory.cast_ptr_to_adr(p) + offset dest_addr = llmemory.cast_ptr_to_adr(newp) + offset llmemory.raw_memcopy(source_addr, dest_addr, llmemory.sizeof(ARRAY.OF) * smallerlength) keepalive_until_here(p) keepalive_until_here(newp) return newp
def string(self, cdataobj, maxlen): space = self.space if isinstance(self.ctitem, ctypeprim.W_CTypePrimitive): cdata = cdataobj._cdata if not cdata: raise oefmt(space.w_RuntimeError, "cannot use string() on %s", space.str_w(cdataobj.repr())) # from pypy.module._cffi_backend import ctypearray length = maxlen if length < 0 and isinstance(self, ctypearray.W_CTypeArray): length = cdataobj.get_array_length() # # pointer to a primitive type of size 1: builds and returns a str if self.ctitem.size == rffi.sizeof(lltype.Char): if length < 0: s = rffi.charp2str(cdata) else: s = rffi.charp2strn(cdata, length) keepalive_until_here(cdataobj) return space.wrap(s) # # pointer to a wchar_t: builds and returns a unicode if self.is_unichar_ptr_or_array(): cdata = rffi.cast(rffi.CWCHARP, cdata) if length < 0: u = rffi.wcharp2unicode(cdata) else: u = rffi.wcharp2unicoden(cdata, length) keepalive_until_here(cdataobj) return space.wrap(u) # return W_CType.string(self, cdataobj, maxlen)
def _call(self, funcaddr, args_w): space = self.space cif_descr = self.cif_descr # 'self' should have been promoted here size = cif_descr.exchange_size mustfree_max_plus_1 = 0 buffer = lltype.malloc(rffi.CCHARP.TO, size, flavor='raw') try: for i in range(len(args_w)): data = rffi.ptradd(buffer, cif_descr.exchange_args[i]) w_obj = args_w[i] argtype = self.fargs[i] if argtype.convert_argument_from_object(data, w_obj): # argtype is a pointer type, and w_obj a list/tuple/str mustfree_max_plus_1 = i + 1 jit_libffi.jit_ffi_call(cif_descr, rffi.cast(rffi.VOIDP, funcaddr), buffer) resultdata = rffi.ptradd(buffer, cif_descr.exchange_result) w_res = self.ctitem.copy_and_convert_to_object(resultdata) finally: for i in range(mustfree_max_plus_1): argtype = self.fargs[i] if isinstance(argtype, W_CTypePointer): data = rffi.ptradd(buffer, cif_descr.exchange_args[i]) flag = get_mustfree_flag(data) if flag == 1: raw_cdata = rffi.cast(rffi.CCHARPP, data)[0] lltype.free(raw_cdata, flavor='raw') lltype.free(buffer, flavor='raw') keepalive_until_here(args_w) return w_res
def ll_shrink_array(p, smallerlength): from rpython.rtyper.lltypesystem.lloperation import llop from rpython.rlib.objectmodel import keepalive_until_here if llop.shrink_array(lltype.Bool, p, smallerlength): return p # done by the GC # XXX we assume for now that the type of p is GcStruct containing a # variable array, with no further pointers anywhere, and exactly one # field in the fixed part -- like STR and UNICODE. TP = lltype.typeOf(p).TO newp = lltype.malloc(TP, smallerlength) assert len(TP._names) == 2 field = getattr(p, TP._names[0]) setattr(newp, TP._names[0], field) ARRAY = getattr(TP, TP._arrayfld) offset = (llmemory.offsetof(TP, TP._arrayfld) + llmemory.itemoffsetof(ARRAY, 0)) source_addr = llmemory.cast_ptr_to_adr(p) + offset dest_addr = llmemory.cast_ptr_to_adr(newp) + offset llmemory.raw_memcopy(source_addr, dest_addr, llmemory.sizeof(ARRAY.OF) * smallerlength) keepalive_until_here(p) keepalive_until_here(newp) return newp
def copy_string_to_raw(src, ptrdst, srcstart, length): """ Copies 'length' characters from the 'src' string to the 'ptrdst' buffer, starting at position 'srcstart'. 'ptrdst' must be a non-gc Array of Char. """ # xxx Warning: same note as above apply: don't do this at home assert length >= 0 # # If the 'split_gc_address_space' option is set, we must copy # manually, character-by-character if rgc.must_split_gc_address_space(): i = 0 while i < length: ptrdst[i] = src.chars[srcstart + i] i += 1 return # # from here, no GC operations can happen asrc = _get_raw_buf(SRC_TP, src, srcstart) adst = llmemory.cast_ptr_to_adr(ptrdst) adst = adst + llmemory.itemoffsetof(typeOf(ptrdst).TO, 0) llmemory.raw_memcopy(asrc, adst, llmemory.sizeof(CHAR_TP) * length) # end of "no GC" section keepalive_until_here(src)
def entry_point(argv): ll_dealloc_trigger_callback = llhelper(FTYPE, dealloc_trigger) rawrefcount.init(ll_dealloc_trigger_callback) ob, p = make_p() if state.seen != []: print "OB COLLECTED REALLY TOO SOON" return 1 rgc.collect() if state.seen != []: print "OB COLLECTED TOO SOON" return 1 objectmodel.keepalive_until_here(p) p = None rgc.collect() if state.seen != [1]: print "OB NOT COLLECTED" return 1 if rawrefcount.next_dead(PyObject) != ob: print "NEXT_DEAD != OB" return 1 if rawrefcount.next_dead(PyObject) != lltype.nullptr(PyObjectS): print "NEXT_DEAD second time != NULL" return 1 if rawrefcount.to_obj(W_Root, ob) is not None: print "to_obj(dead) is not None?" return 1 rawrefcount.mark_deallocating(w_marker, ob) if rawrefcount.to_obj(W_Root, ob) is not w_marker: print "to_obj(marked-dead) is not w_marker" return 1 print "OK!" lltype.free(ob, flavor='raw') return 0
def ll_string2list(RESLIST, src): length = len(src.chars) lst = RESLIST.ll_newlist(length) dst = lst.ll_items() SRC = typeOf(src).TO # STR or UNICODE DST = typeOf(dst).TO # GcArray assert DST.OF is SRC.chars.OF # # If the 'split_gc_address_space' option is set, we must copy # manually, character-by-character if rgc.must_split_gc_address_space(): i = 0 while i < length: dst[i] = src.chars[i] i += 1 return lst # # from here, no GC operations can happen asrc = llmemory.cast_ptr_to_adr(src) + (llmemory.offsetof( SRC, 'chars') + llmemory.itemoffsetof(SRC.chars, 0)) adst = llmemory.cast_ptr_to_adr(dst) + llmemory.itemoffsetof(DST, 0) llmemory.raw_memcopy(asrc, adst, llmemory.sizeof(DST.OF) * length) # end of "no GC" section keepalive_until_here(src) keepalive_until_here(dst) return lst
def _call(self, funcaddr, args_w): space = self.space cif_descr = self.cif_descr size = cif_descr.exchange_size mustfree_max_plus_1 = 0 buffer = lltype.malloc(rffi.CCHARP.TO, size, flavor='raw') try: for i in range(len(args_w)): data = rffi.ptradd(buffer, cif_descr.exchange_args[i]) w_obj = args_w[i] argtype = self.fargs[i] if argtype.convert_argument_from_object(data, w_obj): # argtype is a pointer type, and w_obj a list/tuple/str mustfree_max_plus_1 = i + 1 jit_libffi.jit_ffi_call(cif_descr, rffi.cast(rffi.VOIDP, funcaddr), buffer) resultdata = rffi.ptradd(buffer, cif_descr.exchange_result) w_res = self.ctitem.copy_and_convert_to_object(resultdata) finally: for i in range(mustfree_max_plus_1): argtype = self.fargs[i] if isinstance(argtype, W_CTypePointer): data = rffi.ptradd(buffer, cif_descr.exchange_args[i]) flag = get_mustfree_flag(data) if flag == 1: raw_cdata = rffi.cast(rffi.CCHARPP, data)[0] lltype.free(raw_cdata, flavor='raw') lltype.free(buffer, flavor='raw') keepalive_until_here(args_w) return w_res
def w_getitem(self, space, idx, integer_instead_of_char=False): item = self.get_buffer()[idx] keepalive_until_here(self) if mytype.typecode in 'bBhHil' or (integer_instead_of_char and mytype.typecode in 'cu'): item = rffi.cast(lltype.Signed, item) return space.newint(item) if mytype.typecode in 'IL': return space.newint(item) elif mytype.typecode in 'fd': item = float(item) return space.newfloat(item) elif mytype.typecode == 'c': return space.newbytes(item) elif mytype.typecode == 'u': code = r_uint(ord(item)) # cpython will allow values > sys.maxunicode # while silently truncating the top bits # For now I (arigo) am going to ignore that and # raise a ValueError always here, instead of getting # some invalid utf8-encoded string which makes things # potentially explode left and right. try: item = rutf8.unichr_as_utf8(code, allow_surrogates=True) except rutf8.OutOfRange: raise oefmt( space.w_ValueError, "cannot operate on this array('u') because it contains" " character %s not in range [U+0000; U+10ffff]" " at index %d", 'U+%x' % code, idx) return space.newutf8(item, 1) assert 0, "unreachable"
def w_getitem(self, space, idx, integer_instead_of_char=False): item = self.get_buffer()[idx] keepalive_until_here(self) if mytype.typecode in 'bBhHil' or (integer_instead_of_char and mytype.typecode in 'cu'): item = rffi.cast(lltype.Signed, item) return space.newint(item) if mytype.typecode in 'ILqQ': return space.newint(item) elif mytype.typecode in 'fd': item = float(item) return space.newfloat(item) elif mytype.typecode == 'c': return space.newbytes(item) elif mytype.typecode == 'u': code = r_uint(ord(item)) try: item = rutf8.unichr_as_utf8(code, allow_surrogates=True) except rutf8.OutOfRange: raise oefmt( space.w_ValueError, "cannot operate on this array('u') because it contains" " character %s not in range [U+0000; U+10ffff]" " at index %d", 'U+%x' % code, idx) return space.newtext(item, 1) assert 0, "unreachable"
def object_as_bool(space, w_ob): # convert and cast a Python object to a boolean. Accept an integer # or a float object, up to a CData 'long double'. try: return _standard_object_as_bool(space, w_ob) except _NotStandardObject: pass # from pypy.module._cffi_backend.cdataobj import W_CData from pypy.module._cffi_backend.ctypeprim import W_CTypePrimitiveFloat from pypy.module._cffi_backend.ctypeprim import W_CTypePrimitiveLongDouble is_cdata = isinstance(w_ob, W_CData) if is_cdata and isinstance(w_ob.ctype, W_CTypePrimitiveFloat): if isinstance(w_ob.ctype, W_CTypePrimitiveLongDouble): result = is_nonnull_longdouble(w_ob._cdata) else: result = is_nonnull_float(w_ob._cdata, w_ob.ctype.size) keepalive_until_here(w_ob) return result # if not is_cdata and space.lookup(w_ob, '__float__') is not None: w_io = space.float(w_ob) else: w_io = space.int(w_ob) try: return _standard_object_as_bool(space, w_io) except _NotStandardObject: raise OperationError(space.w_TypeError, space.wrap("integer/float expected"))
def object_as_bool(space, w_ob): # convert and cast a Python object to a boolean. Accept an integer # or a float object, up to a CData 'long double'. try: return _standard_object_as_bool(space, w_ob) except _NotStandardObject: pass # from pypy.module._cffi_backend.cdataobj import W_CData from pypy.module._cffi_backend.ctypeprim import W_CTypePrimitiveFloat from pypy.module._cffi_backend.ctypeprim import W_CTypePrimitiveLongDouble is_cdata = isinstance(w_ob, W_CData) if is_cdata and isinstance(w_ob.ctype, W_CTypePrimitiveFloat): if isinstance(w_ob.ctype, W_CTypePrimitiveLongDouble): result = is_nonnull_longdouble(w_ob._cdata) else: result = is_nonnull_float(w_ob._cdata, w_ob.ctype.size) keepalive_until_here(w_ob) return result # if not is_cdata and space.lookup(w_ob, '__float__') is not None: w_io = space.float(w_ob) else: w_io = space.int(w_ob) try: return _standard_object_as_bool(space, w_io) except _NotStandardObject: raise OperationError(space.w_TypeError, space.wrap("integer/float expected"))
def dump_traceback(self, w_file, all_threads): fileno, w_file = self.get_fileno_and_file(w_file) self.setup() cintf.pypy_faulthandler_dump_traceback( rffi.cast(rffi.INT, fileno), rffi.cast(rffi.INT, all_threads), llmemory.NULL) keepalive_until_here(w_file)
def entry_point(argv): ll_dealloc_trigger_callback = llhelper(FTYPE, dealloc_trigger) rawrefcount.init(ll_dealloc_trigger_callback) ob, p = make_p() if state.seen != []: print "OB COLLECTED REALLY TOO SOON" return 1 rgc.collect() if state.seen != []: print "OB COLLECTED TOO SOON" return 1 objectmodel.keepalive_until_here(p) p = None rgc.collect() if state.seen != [1]: print "OB NOT COLLECTED" return 1 if rawrefcount.next_dead(PyObject) != ob: print "NEXT_DEAD != OB" return 1 if rawrefcount.next_dead(PyObject) != lltype.nullptr(PyObjectS): print "NEXT_DEAD second time != NULL" return 1 print "OK!" lltype.free(ob, flavor='raw') return 0
def copy_and_convert_to_object(self, cdata): space = self.space self.check_complete() ob = cdataobj.W_CDataNewOwning(space, self.size, self) misc._raw_memcopy(cdata, ob._cdata, self.size) keepalive_until_here(ob) return ob
def fn(): a1 = A() a = objectmodel.instantiate(A, nonmovable=True) a.next = a1 # 'a' is known young here, so no write barrier emitted res = rgc.can_move(annlowlevel.cast_instance_to_base_ptr(a)) rgc.collect() objectmodel.keepalive_until_here(a) return res
def cast(self, w_ob): if (isinstance(w_ob, cdataobj.W_CData) and isinstance(w_ob.ctype, W_CTypePrimitiveLongDouble)): w_cdata = self.convert_to_object(w_ob._cdata) keepalive_until_here(w_ob) return w_cdata else: return W_CTypePrimitiveFloat.cast(self, w_ob)
def string(self, cdataobj, maxlen): value = self._get_value(cdataobj._cdata) keepalive_until_here(cdataobj) try: s = self.enumvalues2erators[value] except KeyError: s = str(value) return self.space.wrap(s)
def dump_traceback(self, w_file, all_threads): fileno, w_file = self.get_fileno_and_file(w_file) self.setup() cintf.pypy_faulthandler_dump_traceback( rffi.cast(rffi.INT, fileno), rffi.cast(rffi.INT, all_threads), llmemory.NULL) keepalive_until_here(w_file)
def main(i, j): foo = Foo() foo.nine = -(i + j) t.set(foo) a_char = f(i, j) a_float = libffi_stuff(i, j) keepalive_until_here(foo) return ord(a_char) * 10 + int(a_float)
def convert_from_object(self, cdata, w_ob): space = self.space if isinstance(w_ob, cdataobj.W_CData) and isinstance(w_ob.ctype, W_CTypePrimitiveLongDouble): self._copy_longdouble(w_ob._cdata, cdata) keepalive_until_here(w_ob) else: value = space.float_w(space.float(w_ob)) self._to_longdouble_and_write(value, cdata)
def string(self, cdataobj, maxlen): value = self._get_value(cdataobj._cdata) keepalive_until_here(cdataobj) try: s = self.enumvalues2erators[value] except KeyError: s = str(value) return self.space.wrap(s)
def fn(): a1 = A() a = objectmodel.instantiate(A, nonmovable=True) a.next = a1 # 'a' is known young here, so no write barrier emitted res = rgc.can_move(annlowlevel.cast_instance_to_base_ptr(a)) rgc.collect() objectmodel.keepalive_until_here(a) return res
def setitem(self, space, w_idx, w_item): idx, stop, step = space.decode_index(w_idx, self.len) if step != 0: raise oefmt(self.space.w_TypeError, "can only assign array to array slice") item = self.item_w(w_item) self.get_buffer()[idx] = item keepalive_until_here(self)
def jit_debug(string, arg1=-sys.maxint - 1, arg2=-sys.maxint - 1, arg3=-sys.maxint - 1, arg4=-sys.maxint - 1): """When JITted, cause an extra operation JIT_DEBUG to appear in the graphs. Should not be left after debugging.""" keepalive_until_here( string) # otherwise the whole function call is removed
def convert_from_object(self, cdata, w_ob): space = self.space if (isinstance(w_ob, cdataobj.W_CData) and isinstance(w_ob.ctype, W_CTypePrimitiveLongDouble)): self._copy_longdouble(w_ob._cdata, cdata) keepalive_until_here(w_ob) else: value = space.float_w(space.float(w_ob)) self._to_longdouble_and_write(value, cdata)
def getitem(self, w_index): space = self.space if space.isinstance_w(w_index, space.w_slice): w_o = self._do_getslice(w_index) else: i = space.getindex_w(w_index, space.w_IndexError) ctype = self.ctype._check_subscript_index(self, i) w_o = self._do_getitem(ctype, i) keepalive_until_here(self) return w_o
def ll_arrayclear(p): # Equivalent to memset(array, 0). Only for GcArray(primitive-type) for now. from rpython.rlib.objectmodel import keepalive_until_here length = len(p) ARRAY = lltype.typeOf(p).TO offset = llmemory.itemoffsetof(ARRAY, 0) dest_addr = llmemory.cast_ptr_to_adr(p) + offset llmemory.raw_memclear(dest_addr, llmemory.sizeof(ARRAY.OF) * length) keepalive_until_here(p)
def start_arthreads(): s = allocate_stuff() ident1 = new_thread() ident2 = new_thread() ident3 = new_thread() ident4 = new_thread() ident5 = new_thread() # wait for 4 more seconds, which should be plenty of time time.sleep(4) keepalive_until_here(s)
def keep_buffer_alive_until_here(raw_buf, gc_buf): """ Keeps buffers alive or frees temporary buffers created by alloc_buffer. This must be called after a call to alloc_buffer, usually in a try/finally block. """ if gc_buf: keepalive_until_here(gc_buf) elif raw_buf: lltype.free(raw_buf, flavor='raw')
def copy_raw_to_string(ptrsrc, dst, dststart, length): # xxx Warning: same note as above apply: don't do this at home assert length >= 0 # from here, no GC operations can happen adst = _get_raw_buf(SRC_TP, dst, dststart) asrc = llmemory.cast_ptr_to_adr(ptrsrc) asrc = asrc + llmemory.itemoffsetof(typeOf(ptrsrc).TO, 0) llmemory.raw_memcopy(asrc, adst, llmemory.sizeof(CHAR_TP) * length) # end of "no GC" section keepalive_until_here(dst)
def keep_buffer_alive_until_here(raw_buf, gc_buf, case_num): """ Keeps buffers alive or frees temporary buffers created by alloc_buffer. This must be called after a call to alloc_buffer, usually in a try/finally block. """ keepalive_until_here(gc_buf) if case_num == 1: rgc.unpin(gc_buf) if case_num == 2: lltype.free(raw_buf, flavor='raw')
def free_nonmovingbuffer(data, buf, flag): """ Keep 'data' alive and unpin it if it was pinned (flag==\5). Otherwise free the non-moving copy (flag==\6). """ if flag == '\x05': rgc.unpin(data) if flag == '\x06': lltype.free(buf, flavor='raw') # if flag == '\x04': data was already nonmovable, # we have nothing to clean up keepalive_until_here(data)
def setitem(self, w_index, w_value): space = self.space if space.isinstance_w(w_index, space.w_slice): self._do_setslice(w_index, w_value) else: i = space.getindex_w(w_index, space.w_IndexError) ctype = self.ctype._check_subscript_index(self, i) ctitem = ctype.ctitem ctitem.convert_from_object( rffi.ptradd(self._cdata, i * ctitem.size), w_value) keepalive_until_here(self)
def myfunc(): b = B() b.keep = A() b.data = llmemory.cast_adr_to_ptr(b.keep.addr, PARRAY) b.data[0] = 42 ptr = b.data # normally 'b' could go away as early as here, which would free # the memory held by the instance of A in b.keep... res = ptr[0] # ...so we explicitly keep 'b' alive until here objectmodel.keepalive_until_here(b) return res
def free_nonmovingbuffer(data, buf, is_pinned, is_raw): """ Keep 'data' alive and unpin it if it was pinned ('is_pinned' is true). Otherwise free the non-moving copy ('is_raw' is true). """ if is_pinned: rgc.unpin(data) if is_raw: lltype.free(buf, flavor='raw') # if is_pinned and is_raw are false: data was already nonmovable, # we have nothing to clean up keepalive_until_here(data)
def f(n): states = [] while n > 0: mydriver.jit_merge_point(n=n, states=states) state = State() states.append(state) x = X(state) do_stuff() state.num *= 1000 do_stuff() keepalive_until_here(x) n -= 1 return states