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_y(): if not helper.inst: helper.inst = Y() helper.inst.x = 101 check(rgc.pin(helper.inst)) else: check(rgc._is_pinned(helper.inst)) return helper.inst
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 g(): a = A() assert rgc.pin(a) a.x = 100 wr = weakref.ref(a) llop.gc__collect(lltype.Void) assert wr() is not None assert a.x == 100 return wr
def get_instances(): if not helper.initialised: helper.inst1 = Y() helper.inst1.x = 101 check(rgc.pin(helper.inst1)) # helper.inst2 = Y() helper.inst2.x = 102 # helper.inst3 = Y() helper.inst3.x = 103 check(rgc.pin(helper.inst3)) # helper.initialised = True # check(rgc._is_pinned(helper.inst1)) check(not rgc._is_pinned(helper.inst2)) check(rgc._is_pinned(helper.inst3)) return (helper.inst1, helper.inst2, helper.inst3)
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 execute_uv(self, loop, k): baton = lltype.malloc(uv_baton_t, flavor="raw") rgc.pin(baton) exb = self._fn.prep_exb(self._args) buffer_array = rffi.cast(rffi.VOIDPP, exb) work_data_container[rffi.cast(rffi.INT, baton)] = (k, exb, self._fn) cif = self._fn._cd for i in range(cif.nargs): data = rffi.ptradd(exb, cif.exchange_args[i]) buffer_array[i] = data resultdata = rffi.ptradd(exb, cif.exchange_result_libffi) ffi_run(baton, loop, rffi.cast(rffi.VOIDP, cif), rffi.cast(rffi.VOIDP, self._fn._f_ptr), rffi.cast(rffi.VOIDP, exb), rffi.cast(rffi.VOIDP, resultdata), _work_cb)
def get_y(n): if not helper.inst: helper.inst = Y() helper.inst.x = 101 helper.pinned = True check(rgc.pin(helper.inst)) elif n < 100 and helper.pinned: rgc.unpin(helper.inst) helper.pinned = False # if helper.pinned: check(rgc._is_pinned(helper.inst)) helper.count_pinned += 1 else: check(not rgc._is_pinned(helper.inst)) helper.count_unpinned += 1 return helper.inst
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 f(): a = A() ref = weakref.ref(a) assert not rgc.pin(ref)
def f(): a = A() b = B() assert not rgc.pin(a) assert not rgc.pin(b)
def check_rewrite(self, frm_operations, to_operations, **namespace): # objects to use inside the test A = lltype.GcArray(lltype.Signed) adescr = get_array_descr(self.gc_ll_descr, A) adescr.tid = 4321 alendescr = adescr.lendescr # pinned_obj_type = lltype.GcStruct('PINNED_STRUCT', ('my_int', lltype.Signed)) pinned_obj_my_int_descr = get_field_descr(self.gc_ll_descr, pinned_obj_type, 'my_int') pinned_obj_ptr = lltype.malloc(pinned_obj_type) pinned_obj_gcref = lltype.cast_opaque_ptr(llmemory.GCREF, pinned_obj_ptr) assert rgc.pin(pinned_obj_gcref) # notpinned_obj_type = lltype.GcStruct('NOT_PINNED_STRUCT', ('my_int', lltype.Signed)) notpinned_obj_my_int_descr = get_field_descr(self.gc_ll_descr, notpinned_obj_type, 'my_int') notpinned_obj_ptr = lltype.malloc(notpinned_obj_type) notpinned_obj_gcref = lltype.cast_opaque_ptr(llmemory.GCREF, notpinned_obj_ptr) # ptr_array_descr = self.cpu.arraydescrof(MovableObjectTracker.ptr_array_type) # vtable_descr = self.gc_ll_descr.fielddescr_vtable O = lltype.GcStruct('O', ('parent', rclass.OBJECT), ('x', lltype.Signed)) o_vtable = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True) register_known_gctype(self.cpu, o_vtable, O) # tiddescr = self.gc_ll_descr.fielddescr_tid wbdescr = self.gc_ll_descr.write_barrier_descr WORD = globals()['WORD'] # strdescr = self.gc_ll_descr.str_descr unicodedescr = self.gc_ll_descr.unicode_descr strlendescr = strdescr.lendescr unicodelendescr = unicodedescr.lendescr casmdescr = JitCellToken() clt = FakeLoopToken() clt._ll_initial_locs = [0, 8] frame_info = lltype.malloc(jitframe.JITFRAMEINFO, flavor='raw') clt.frame_info = frame_info frame_info.jfi_frame_depth = 13 frame_info.jfi_frame_size = 255 framedescrs = self.gc_ll_descr.getframedescrs(self.cpu) framelendescr = framedescrs.arraydescr.lendescr jfi_frame_depth = framedescrs.jfi_frame_depth jfi_frame_size = framedescrs.jfi_frame_size jf_frame_info = framedescrs.jf_frame_info signedframedescr = self.cpu.signedframedescr floatframedescr = self.cpu.floatframedescr casmdescr.compiled_loop_token = clt tzdescr = None # noone cares # namespace.update(locals()) # for funcname in self.gc_ll_descr._generated_functions: namespace[funcname] = self.gc_ll_descr.get_malloc_fn(funcname) namespace[funcname + '_descr'] = getattr(self.gc_ll_descr, '%s_descr' % funcname) # ops = parse(frm_operations, namespace=namespace) operations = self.gc_ll_descr.rewrite_assembler(self.cpu, ops.operations, []) # make the array containing the GCREF's accessible inside the tests. # This must be done after we call 'rewrite_assembler'. Before that # call 'last_moving_obj_tracker' is None or filled with some old # value. namespace['ptr_array_gcref'] = self.gc_ll_descr.last_moving_obj_tracker.ptr_array_gcref expected = parse(to_operations % Evaluator(namespace), namespace=namespace) equaloplists(operations, expected.operations) lltype.free(frame_info, flavor='raw')
def check_rewrite(self, frm_operations, to_operations, **namespace): # objects to use inside the test A = lltype.GcArray(lltype.Signed) adescr = get_array_descr(self.gc_ll_descr, A) adescr.tid = 4321 alendescr = adescr.lendescr # pinned_obj_type = lltype.GcStruct('PINNED_STRUCT', ('my_int', lltype.Signed)) pinned_obj_my_int_descr = get_field_descr(self.gc_ll_descr, pinned_obj_type, 'my_int') pinned_obj_ptr = lltype.malloc(pinned_obj_type) pinned_obj_gcref = lltype.cast_opaque_ptr(llmemory.GCREF, pinned_obj_ptr) assert rgc.pin(pinned_obj_gcref) # notpinned_obj_type = lltype.GcStruct('NOT_PINNED_STRUCT', ('my_int', lltype.Signed)) notpinned_obj_my_int_descr = get_field_descr(self.gc_ll_descr, notpinned_obj_type, 'my_int') notpinned_obj_ptr = lltype.malloc(notpinned_obj_type) notpinned_obj_gcref = lltype.cast_opaque_ptr(llmemory.GCREF, notpinned_obj_ptr) # ptr_array_descr = self.cpu.arraydescrof(MovableObjectTracker.ptr_array_type) # vtable_descr = self.gc_ll_descr.fielddescr_vtable O = lltype.GcStruct('O', ('parent', rclass.OBJECT), ('x', lltype.Signed)) o_vtable = lltype.malloc(rclass.OBJECT_VTABLE, immortal=True) # tiddescr = self.gc_ll_descr.fielddescr_tid wbdescr = self.gc_ll_descr.write_barrier_descr WORD = globals()['WORD'] # strdescr = self.gc_ll_descr.str_descr unicodedescr = self.gc_ll_descr.unicode_descr strlendescr = strdescr.lendescr unicodelendescr = unicodedescr.lendescr casmdescr = JitCellToken() clt = FakeLoopToken() clt._ll_initial_locs = [0, 8] frame_info = lltype.malloc(jitframe.JITFRAMEINFO, flavor='raw') clt.frame_info = frame_info frame_info.jfi_frame_depth = 13 frame_info.jfi_frame_size = 255 framedescrs = self.gc_ll_descr.getframedescrs(self.cpu) framelendescr = framedescrs.arraydescr.lendescr jfi_frame_depth = framedescrs.jfi_frame_depth jfi_frame_size = framedescrs.jfi_frame_size jf_frame_info = framedescrs.jf_frame_info signedframedescr = self.cpu.signedframedescr floatframedescr = self.cpu.floatframedescr casmdescr.compiled_loop_token = clt tzdescr = None # noone cares # namespace.update(locals()) # for funcname in self.gc_ll_descr._generated_functions: namespace[funcname] = self.gc_ll_descr.get_malloc_fn(funcname) namespace[funcname + '_descr'] = getattr(self.gc_ll_descr, '%s_descr' % funcname) # ops = parse(frm_operations, namespace=namespace) operations = self.gc_ll_descr.rewrite_assembler(self.cpu, ops.operations, []) # make the array containing the GCREF's accessible inside the tests. # This must be done after we call 'rewrite_assembler'. Before that # call 'last_moving_obj_tracker' is None or filled with some old # value. namespace['ptr_array_gcref'] = self.gc_ll_descr.last_moving_obj_tracker.ptr_array_gcref expected = parse(to_operations % Evaluator(namespace), namespace=namespace) equaloplists(operations, expected.operations) lltype.free(frame_info, flavor='raw')