def get_raw_address_of_string(space, w_x): """Special case for ffi.from_buffer(string). Returns a 'char *' that is valid as long as the string object is alive. Two calls to ffi.from_buffer(same_string) are guaranteed to return the same pointer. """ from rpython.rtyper.annlowlevel import llstr from rpython.rtyper.lltypesystem.rstr import STR from rpython.rtyper.lltypesystem import llmemory from rpython.rlib import rgc cache = space.fromcache(RawBytesCache) rawbytes = cache.wdict.get(w_x) if rawbytes is None: data = space.bytes_w(w_x) if (we_are_translated() and not rgc.can_move(data) and not rgc.must_split_gc_address_space()): lldata = llstr(data) data_start = (llmemory.cast_ptr_to_adr(lldata) + rffi.offsetof(STR, 'chars') + llmemory.itemoffsetof(STR.chars, 0)) data_start = rffi.cast(rffi.CCHARP, data_start) data_start[len(data)] = '\x00' # write the final extra null return data_start rawbytes = RawBytes(data) cache.wdict.set(w_x, rawbytes) return rawbytes.ptr
def alloc_buffer(count): """ Returns a (raw_buffer, gc_buffer, case_num) triple, allocated with count bytes. The raw_buffer can be safely passed to a native function which expects it to not move. Call str_from_buffer with the returned values to get a safe high-level string. When the garbage collector cooperates, this allows for the process to be performed without an extra copy. Make sure to call keep_buffer_alive_until_here on the returned values. """ new_buf = mallocfn(count) pinned = 0 if rgc.can_move(new_buf): if rgc.pin(new_buf): pinned = 1 else: raw_buf = lltype.malloc(TYPEP.TO, count, flavor='raw') return raw_buf, new_buf, 2 # # following code is executed if: # - rgc.can_move(data) and rgc.pin(data) both returned true # - rgc.can_move(data) returned false data_start = cast_ptr_to_adr(new_buf) + \ offsetof(STRTYPE, 'chars') + itemoffsetof(STRTYPE.chars, 0) return cast(TYPEP, data_start), new_buf, pinned
def get_nonmovingbuffer(data): """ Either returns a non-moving copy or performs neccessary pointer arithmetic to return a pointer to the characters of a string if the string is already nonmovable or could be pinned. Must be followed by a free_nonmovingbuffer call. First bool returned indicates if 'data' was pinned. Second bool returned indicates if we did a raw alloc because pinning failed. Both bools should never be true at the same time. """ lldata = llstrtype(data) count = len(data) pinned = False if rgc.can_move(data): if rgc.pin(data): pinned = True else: buf = lltype.malloc(TYPEP.TO, count, flavor='raw') copy_string_to_raw(lldata, buf, 0, count) return buf, pinned, True # ^^^ raw malloc used to get a nonmovable copy # # following code is executed if: # - rgc.can_move(data) and rgc.pin(data) both returned true # - rgc.can_move(data) returned false data_start = cast_ptr_to_adr(lldata) + \ offsetof(STRTYPE, 'chars') + itemoffsetof(STRTYPE.chars, 0) return cast(TYPEP, data_start), pinned, False
def get_raw_address_of_string(space, w_x): """Special case for ffi.from_buffer(string). Returns a 'char *' that is valid as long as the string object is alive. Two calls to ffi.from_buffer(same_string) are guaranteed to return the same pointer. """ from rpython.rtyper.annlowlevel import llstr from rpython.rtyper.lltypesystem.rstr import STR from rpython.rtyper.lltypesystem import llmemory from rpython.rlib import rgc cache = space.fromcache(RawBytesCache) rawbytes = cache.wdict.get(w_x) if rawbytes is None: data = space.str_w(w_x) if we_are_translated() and not rgc.can_move(data): lldata = llstr(data) data_start = (llmemory.cast_ptr_to_adr(lldata) + rffi.offsetof(STR, 'chars') + llmemory.itemoffsetof(STR.chars, 0)) data_start = rffi.cast(rffi.CCHARP, data_start) data_start[len(data)] = '\x00' # write the final extra null return data_start rawbytes = RawBytes(data) cache.wdict.set(w_x, rawbytes) return rawbytes.ptr
def func(): #try: a = rgc.malloc_nonmovable(TP, 3, zero=True) rgc.collect() if a: assert not rgc.can_move(a) return 1 return 0
def fn(n): s = str(n) if not rgc.can_move(s): return 13 res = int(rgc.pin(s)) if res: rgc.unpin(s) return res
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 func(): try: a = rgc.malloc_nonmovable(TP) rgc.collect() if a: assert not rgc.can_move(a) return 1 return 0 except Exception: return 2
def fn(n): from rpython.rlib.debug import debug_print s = str(n) if not rgc.can_move(s): return 13 res = int(rgc.pin(s)) if res: res += int(rgc._is_pinned(s)) rgc.unpin(s) return res
def get_nonmovingbuffer(data): """ Either returns a non-moving copy or performs neccessary pointer arithmetic to return a pointer to the characters of a string if the string is already nonmovable. Must be followed by a free_nonmovingbuffer call. """ lldata = llstrtype(data) if rgc.can_move(data): count = len(data) buf = lltype.malloc(TYPEP.TO, count, flavor='raw') copy_string_to_raw(lldata, buf, 0, count) return buf else: data_start = cast_ptr_to_adr(lldata) + \ offsetof(STRTYPE, 'chars') + itemoffsetof(STRTYPE.chars, 0) return cast(TYPEP, data_start)
def get_nonmovingbuffer(data): """ Either returns a non-moving copy or performs neccessary pointer arithmetic to return a pointer to the characters of a string if the string is already nonmovable or could be pinned. Must be followed by a free_nonmovingbuffer call. Also returns a char: * \4: no pinning, returned pointer is inside 'data' which is nonmovable * \5: 'data' was pinned, returned pointer is inside * \6: pinning failed, returned pointer is raw malloced For strings (not unicodes), the len()th character of the resulting raw buffer is available, but not initialized. Use get_nonmovingbuffer_final_null() instead of get_nonmovingbuffer() to get a regular null-terminated "char *". """ lldata = llstrtype(data) count = len(data) if we_are_translated_to_c() and not rgc.can_move(data): flag = '\x04' else: if we_are_translated_to_c() and rgc.pin(data): flag = '\x05' else: buf = lltype.malloc(TYPEP.TO, count + (TYPEP is CCHARP), flavor='raw') copy_string_to_raw(lldata, buf, 0, count) return buf, '\x06' # ^^^ raw malloc used to get a nonmovable copy # # following code is executed after we're translated to C, if: # - rgc.can_move(data) and rgc.pin(data) both returned true # - rgc.can_move(data) returned false data_start = cast_ptr_to_adr(lldata) + \ offsetof(STRTYPE, 'chars') + itemoffsetof(STRTYPE.chars, 0) return cast(TYPEP, data_start), flag
def func(): a = rgc.malloc_nonmovable(TP, 3) if a: assert not rgc.can_move(a) return 1 return 0
def func(): return rgc.can_move(lltype.malloc(TP, 1))
def fn(): return rgc.can_move(A())
def f(i): if i: return rgc.can_move(lltype.malloc(T0)) else: return rgc.can_move(lltype.malloc(T1, 1))