def __del__(self): if self.ll_cif: lltype.free(self.ll_cif, flavor='raw') self.ll_cif = lltype.nullptr(FFI_CIFP.TO) if self.ll_argtypes: lltype.free(self.ll_argtypes, flavor='raw') self.ll_argtypes = lltype.nullptr(FFI_TYPE_PP.TO)
def EnumKey(space, w_hkey, index): """string = EnumKey(key, index) - Enumerates subkeys of an open registry key. key is an already open key, or any one of the predefined HKEY_* constants. index is an integer that identifies the index of the key to retrieve. The function retrieves the name of one subkey each time it is called. It is typically called repeatedly until an EnvironmentError exception is raised, indicating no more values are available.""" hkey = hkey_w(w_hkey, space) null_dword = lltype.nullptr(rwin32.LPDWORD.TO) # max key name length is 255 buf = lltype.malloc(rffi.CCHARP.TO, 256, flavor="raw") try: retValueSize = lltype.malloc(rwin32.LPDWORD.TO, 1, flavor="raw") try: retValueSize[0] = 256 # includes NULL terminator ret = rwinreg.RegEnumKeyEx( hkey, index, buf, retValueSize, null_dword, None, null_dword, lltype.nullptr(rwin32.PFILETIME.TO) ) if ret != 0: raiseWindowsError(space, ret, "RegEnumKeyEx") return space.wrap(rffi.charp2str(buf)) finally: lltype.free(retValueSize, flavor="raw") finally: lltype.free(buf, flavor="raw")
def test_carray_to_ll(): A = lltype.Array(lltype.Signed, hints={'nolength': True}) a = lltype.malloc(A, 10, flavor='raw') a2 = lltype.malloc(A, 10, flavor='raw') a[0] = 100 a[1] = 101 a[2] = 110 ac = lltype2ctypes(a) b = ctypes2lltype(lltype.Ptr(A), ac) assert lltype.typeOf(b) == lltype.Ptr(A) assert b == a assert not (b != a) assert a == b assert not (a != b) assert b != lltype.nullptr(A) assert not (b == lltype.nullptr(A)) assert lltype.nullptr(A) != b assert not (lltype.nullptr(A) == b) assert b != a2 assert not (b == a2) assert a2 != b assert not (a2 == b) assert b[2] == 110 b[2] *= 2 assert a[2] == 220 a[2] *= 3 assert b[2] == 660 lltype.free(a, flavor='raw') lltype.free(a2, flavor='raw')
def PyErr_GetExcInfo(space, ptype, pvalue, ptraceback): """---Cython extension--- Retrieve the exception info, as known from ``sys.exc_info()``. This refers to an exception that was already caught, not to an exception that was freshly raised. Returns new references for the three objects, any of which may be *NULL*. Does not modify the exception info state. .. note:: This function is not normally used by code that wants to handle exceptions. Rather, it can be used when code needs to save and restore the exception state temporarily. Use :c:func:`PyErr_SetExcInfo` to restore or clear the exception state. """ ec = space.getexecutioncontext() operror = ec.sys_exc_info() if operror: ptype[0] = make_ref(space, operror.w_type) pvalue[0] = make_ref(space, operror.get_w_value(space)) ptraceback[0] = make_ref(space, space.wrap(operror.get_traceback())) else: ptype[0] = lltype.nullptr(PyObject.TO) pvalue[0] = lltype.nullptr(PyObject.TO) ptraceback[0] = lltype.nullptr(PyObject.TO)
def __del__(self): if self.lib: c_dlclose(self.lib) self.lib = lltype.nullptr(rffi.CCHARP.TO) if self.ll_libname: lltype.free(self.ll_libname, flavor='raw') self.ll_libname = lltype.nullptr(rffi.CCHARP.TO)
def setup(self): GCBase.setup(self) self.heap_usage = 0 # at the end of the latest collection self.bytes_malloced = 0 # since the latest collection self.bytes_malloced_threshold = self.param_start_heap_size self.total_collection_time = 0.0 self.malloced_objects = lltype.nullptr(self.HDR) self.malloced_objects_with_finalizer = lltype.nullptr(self.HDR) # these are usually only the small bits of memory that make a # weakref object self.objects_with_weak_pointers = lltype.nullptr(self.HDR) # pools, for x_swap_pool(): # 'curpool' is the current pool, lazily allocated (i.e. NULL means # the current POOL object is not yet malloc'ed). POOL objects are # usually at the start of a linked list of objects, via the HDRs. # The exception is 'curpool' whose linked list of objects is in # 'self.malloced_objects' instead of in the header of 'curpool'. # POOL objects are never in the middle of a linked list themselves. # XXX a likely cause for the current problems with pools is: # not all objects live in malloced_objects, some also live in # malloced_objects_with_finalizer and objects_with_weak_pointers self.curpool = lltype.nullptr(self.POOL) # 'poolnodes' is a linked list of all such linked lists. Each # linked list will usually start with a POOL object, but it can # also contain only normal objects if the POOL object at the head # was already freed. The objects in 'malloced_objects' are not # found via 'poolnodes'. self.poolnodes = lltype.nullptr(self.POOLNODE) self.collect_in_progress = False self.prev_collect_end_time = 0.0
def test_cstruct_to_ll(): S = lltype.Struct('S', ('x', lltype.Signed), ('y', lltype.Signed)) s = lltype.malloc(S, flavor='raw') s2 = lltype.malloc(S, flavor='raw') s.x = 123 sc = lltype2ctypes(s) t = ctypes2lltype(lltype.Ptr(S), sc) assert lltype.typeOf(t) == lltype.Ptr(S) assert s == t assert not (s != t) assert t == s assert not (t != s) assert t != lltype.nullptr(S) assert not (t == lltype.nullptr(S)) assert lltype.nullptr(S) != t assert not (lltype.nullptr(S) == t) assert t != s2 assert not (t == s2) assert s2 != t assert not (s2 == t) assert t.x == 123 t.x += 1 assert s.x == 124 s.x += 1 assert t.x == 125 lltype.free(s, flavor='raw') lltype.free(s2, flavor='raw')
def PyBuffer_FillInfo(space, view, obj, buf, length, readonly, flags): """ Fills in a buffer-info structure correctly for an exporter that can only share a contiguous chunk of memory of "unsigned bytes" of the given length. Returns 0 on success and -1 (with raising an error) on error. This is not a complete re-implementation of the CPython API; it only provides a subset of CPython's behavior. """ view.c_buf = buf view.c_len = length view.c_obj = obj Py_IncRef(space, obj) view.c_itemsize = 1 if flags & PyBUF_WRITABLE: rffi.setintfield(view, "c_readonly", 0) else: rffi.setintfield(view, "c_readonly", 1) rffi.setintfield(view, "c_ndim", 0) view.c_format = lltype.nullptr(rffi.CCHARP.TO) view.c_shape = lltype.nullptr(Py_ssize_tP.TO) view.c_strides = lltype.nullptr(Py_ssize_tP.TO) view.c_suboffsets = lltype.nullptr(Py_ssize_tP.TO) view.c_internal = lltype.nullptr(rffi.VOIDP.TO) return 0
def test_AsEncodedObject(self, space, api): ptr = space.wrap('abc') errors = rffi.str2charp("strict") encoding = rffi.str2charp("hex") res = api.PyString_AsEncodedObject( ptr, encoding, errors) assert space.unwrap(res) == "616263" res = api.PyString_AsEncodedObject( ptr, encoding, lltype.nullptr(rffi.CCHARP.TO)) assert space.unwrap(res) == "616263" rffi.free_charp(encoding) encoding = rffi.str2charp("unknown_encoding") self.raises(space, api, LookupError, api.PyString_AsEncodedObject, ptr, encoding, errors) rffi.free_charp(encoding) rffi.free_charp(errors) res = api.PyString_AsEncodedObject( ptr, lltype.nullptr(rffi.CCHARP.TO), lltype.nullptr(rffi.CCHARP.TO)) assert space.unwrap(res) == "abc" self.raises(space, api, TypeError, api.PyString_AsEncodedObject, space.wrap(2), lltype.nullptr(rffi.CCHARP.TO), lltype.nullptr(rffi.CCHARP.TO) )
def __del__(self): if self.ll_cif: lltype.free(self.ll_cif, flavor="raw", track_allocation=False) self.ll_cif = lltype.nullptr(FFI_CIFP.TO) if self.ll_argtypes: lltype.free(self.ll_argtypes, flavor="raw", track_allocation=False) self.ll_argtypes = lltype.nullptr(FFI_TYPE_PP.TO)
def test_blit_rect(self): surface = RSDL.CreateRGBSurface(0, 150, 50, 32, r_uint(0x000000FF), r_uint(0x0000FF00), r_uint(0x00FF0000), r_uint(0xFF000000)) fmt = surface.c_format color = RSDL.MapRGB(fmt, 255, 0, 0) RSDL.FillRect(surface, lltype.nullptr(RSDL.Rect), color) paintrect = RSDL_helper.mallocrect(75, 0, 150, 50) dstrect = lltype.malloc(RSDL.Rect, flavor='raw') try: color = RSDL.MapRGB(fmt, 255, 128, 0) RSDL.FillRect(surface, paintrect, color) rffi.setintfield(dstrect, 'c_x', 10) rffi.setintfield(dstrect, 'c_y', 10) rffi.setintfield(dstrect, 'c_w', 150) rffi.setintfield(dstrect, 'c_h', 50) RSDL.BlitSurface(surface, lltype.nullptr(RSDL.Rect), self.screen, dstrect) RSDL.Flip(self.screen) finally: lltype.free(dstrect, flavor='raw') lltype.free(paintrect, flavor='raw') RSDL.FreeSurface(surface) self.check("Half Red/Orange rectangle(150px * 50px) at the top left, 10 pixels from the border")
def EnumKey(space, w_hkey, index): """string = EnumKey(key, index) - Enumerates subkeys of an open registry key. key is an already open key, or any one of the predefined HKEY_* constants. index is an integer that identifies the index of the key to retrieve. The function retrieves the name of one subkey each time it is called. It is typically called repeatedly until an EnvironmentError exception is raised, indicating no more values are available.""" hkey = hkey_w(w_hkey, space) null_dword = lltype.nullptr(rwin32.LPDWORD.TO) # The Windows docs claim that the max key name length is 255 # characters, plus a terminating nul character. However, # empirical testing demonstrates that it is possible to # create a 256 character key that is missing the terminating # nul. RegEnumKeyEx requires a 257 character buffer to # retrieve such a key name. with lltype.scoped_alloc(rffi.CCHARP.TO, 257) as buf: with lltype.scoped_alloc(rwin32.LPDWORD.TO, 1) as retValueSize: retValueSize[0] = r_uint(257) # includes NULL terminator ret = rwinreg.RegEnumKeyEx(hkey, index, buf, retValueSize, null_dword, None, null_dword, lltype.nullptr(rwin32.PFILETIME.TO)) if ret != 0: raiseWindowsError(space, ret, 'RegEnumKeyEx') return space.wrap(rffi.charp2str(buf))
def test_ascii_codec(self, space, api): s = 'abcdefg' data = rffi.str2charp(s) w_u = api.PyUnicode_DecodeASCII(data, len(s), lltype.nullptr(rffi.CCHARP.TO)) assert space.eq_w(w_u, space.wrap(u"abcdefg")) rffi.free_charp(data) s = 'abcd\xFF' data = rffi.str2charp(s) self.raises(space, api, UnicodeDecodeError, api.PyUnicode_DecodeASCII, data, len(s), lltype.nullptr(rffi.CCHARP.TO)) rffi.free_charp(data) uni = u'abcdefg' data = rffi.unicode2wcharp(uni) w_s = api.PyUnicode_EncodeASCII(data, len(uni), lltype.nullptr(rffi.CCHARP.TO)) assert space.eq_w(space.wrap("abcdefg"), w_s) rffi.free_wcharp(data) u = u'äbcdéfg' data = rffi.unicode2wcharp(u) w_s = api.PyUnicode_EncodeASCII(data, len(u), lltype.nullptr(rffi.CCHARP.TO)) self.raises(space, api, UnicodeEncodeError, api.PyUnicode_EncodeASCII, data, len(u), lltype.nullptr(rffi.CCHARP.TO)) rffi.free_wcharp(data)
def init_typeobject(space): # Probably a hack space.model.typeorder[W_PyCTypeObject] = [(W_PyCTypeObject, None), (W_TypeObject, None), (W_Root, None)] make_typedescr(space.w_type.instancetypedef, basestruct=PyTypeObject, alloc=type_alloc, attach=type_attach, realize=type_realize, dealloc=type_dealloc) # some types are difficult to create because of cycles. # - object.ob_type = type # - type.ob_type = type # - tuple.ob_type = type # - type.tp_base = object # - tuple.tp_base = object # - type.tp_bases is a tuple # - object.tp_bases is a tuple # - tuple.tp_bases is a tuple # insert null placeholders to please create_ref() track_reference(space, lltype.nullptr(PyObject.TO), space.w_type) track_reference(space, lltype.nullptr(PyObject.TO), space.w_object) track_reference(space, lltype.nullptr(PyObject.TO), space.w_tuple) track_reference(space, lltype.nullptr(PyObject.TO), space.w_str) # create the objects py_type = create_ref(space, space.w_type) py_object = create_ref(space, space.w_object) py_tuple = create_ref(space, space.w_tuple) py_str = create_ref(space, space.w_str) # form cycles pto_type = rffi.cast(PyTypeObjectPtr, py_type) py_type.c_ob_type = pto_type py_object.c_ob_type = pto_type py_tuple.c_ob_type = pto_type pto_object = rffi.cast(PyTypeObjectPtr, py_object) pto_type.c_tp_base = pto_object pto_tuple = rffi.cast(PyTypeObjectPtr, py_tuple) pto_tuple.c_tp_base = pto_object pto_type.c_tp_bases.c_ob_type = pto_tuple pto_object.c_tp_bases.c_ob_type = pto_tuple pto_tuple.c_tp_bases.c_ob_type = pto_tuple for typ in (py_type, py_object, py_tuple, py_str): heaptype = rffi.cast(PyHeapTypeObject, typ) heaptype.c_ht_name.c_ob_type = pto_type # Restore the mapping track_reference(space, py_type, space.w_type, replace=True) track_reference(space, py_object, space.w_object, replace=True) track_reference(space, py_tuple, space.w_tuple, replace=True) track_reference(space, py_str, space.w_str, replace=True)
def do_poll(self, space, timeout): from pypy.module._multiprocessing.interp_win32 import ( _PeekNamedPipe, _GetTickCount, _Sleep) from pypy.rlib import rwin32 from pypy.interpreter.error import wrap_windowserror bytes_ptr = lltype.malloc(rffi.CArrayPtr(rwin32.DWORD).TO, 1, flavor='raw') try: if not _PeekNamedPipe(self.handle, rffi.NULL, 0, lltype.nullptr(rwin32.LPDWORD.TO), bytes_ptr, lltype.nullptr(rwin32.LPDWORD.TO)): raise wrap_windowserror(space, rwin32.lastWindowsError()) bytes = bytes_ptr[0] finally: lltype.free(bytes_ptr, flavor='raw') if timeout == 0.0: return bytes > 0 block = timeout < 0 if not block: # XXX does not check for overflow deadline = intmask(_GetTickCount()) + int(1000 * timeout + 0.5) else: deadline = 0 _Sleep(0) delay = 1 while True: bytes_ptr = lltype.malloc(rffi.CArrayPtr(rwin32.DWORD).TO, 1, flavor='raw') try: if not _PeekNamedPipe(self.handle, rffi.NULL, 0, lltype.nullptr(rwin32.LPDWORD.TO), bytes_ptr, lltype.nullptr(rwin32.LPDWORD.TO)): raise wrap_windowserror(space, rwin32.lastWindowsError()) bytes = bytes_ptr[0] finally: lltype.free(bytes_ptr, flavor='raw') if bytes > 0: return True if not block: now = intmask(_GetTickCount()) if now > deadline: return False diff = deadline - now if delay > diff: delay = diff else: delay += 1 if delay >= 20: delay = 20 _Sleep(delay)
def __del__(self): AbstractFuncPtr.__del__(self) if self.ll_closure: closureHeap.free(self.ll_closure) self.ll_closure = lltype.nullptr(FFI_CLOSUREP.TO) if self.ll_userdata: lltype.free(self.ll_userdata, flavor='raw') self.ll_userdata = lltype.nullptr(USERDATA_P.TO)
def main(a, b, x): xp = lltype.malloc(XP) xp.vable_access = lltype.nullptr(XP_ACCESS) xp.x = x xp.p = lltype.nullptr(S) e = lltype.malloc(E2) e.xp = xp f(e, a, b) return e.w + xp.p.a + xp.p.b
def select(inl, outl, excl, timeout=-1.0): nfds = 0 if inl: ll_inl = lltype.malloc(_c.fd_set.TO, flavor="raw") _c.FD_ZERO(ll_inl) for i in inl: _c.FD_SET(i, ll_inl) if i > nfds: nfds = i else: ll_inl = lltype.nullptr(_c.fd_set.TO) if outl: ll_outl = lltype.malloc(_c.fd_set.TO, flavor="raw") _c.FD_ZERO(ll_outl) for i in outl: _c.FD_SET(i, ll_outl) if i > nfds: nfds = i else: ll_outl = lltype.nullptr(_c.fd_set.TO) if excl: ll_excl = lltype.malloc(_c.fd_set.TO, flavor="raw") _c.FD_ZERO(ll_excl) for i in excl: _c.FD_SET(i, ll_excl) if i > nfds: nfds = i else: ll_excl = lltype.nullptr(_c.fd_set.TO) if timeout != -1.0: ll_timeval = lltype.malloc(_c.timeval, flavor="raw") frac = math.fmod(timeout, 1.0) ll_timeval.c_tv_sec = int(timeout) ll_timeval.c_tv_usec = int((timeout - int(timeout)) * 1000000.0) else: ll_timeval = lltype.nullptr(_c.timeval) try: res = _c.select(nfds + 1, ll_inl, ll_outl, ll_excl, ll_timeval) if res == -1: raise SelectError(_c.geterrno()) if res == 0: return ([], [], []) else: return ( [i for i in inl if _c.FD_ISSET(i, ll_inl)], [i for i in outl if _c.FD_ISSET(i, ll_outl)], [i for i in excl if _c.FD_ISSET(i, ll_excl)], ) finally: if ll_inl: lltype.free(ll_inl, flavor="raw") if ll_outl: lltype.free(ll_outl, flavor="raw") if ll_excl: lltype.free(ll_excl, flavor="raw") if ll_timeval: lltype.free(ll_timeval, flavor="raw")
def main(a, b, x): pq = lltype.malloc(PQ) pq.vable_access = lltype.nullptr(PQ_ACCESS) pq.p = lltype.nullptr(S) pq.q = pq.p e = lltype.malloc(E3) e.pq = pq f(e, a, b) return e.w
def select(inl, outl, excl, timeout=-1.0): nfds = 0 if inl: ll_inl = lltype.malloc(_c.fd_set.TO, flavor='raw') _c.FD_ZERO(ll_inl) for i in inl: _c.FD_SET(i, ll_inl) if i > nfds: nfds = i else: ll_inl = lltype.nullptr(_c.fd_set.TO) if outl: ll_outl = lltype.malloc(_c.fd_set.TO, flavor='raw') _c.FD_ZERO(ll_outl) for i in outl: _c.FD_SET(i, ll_outl) if i > nfds: nfds = i else: ll_outl = lltype.nullptr(_c.fd_set.TO) if excl: ll_excl = lltype.malloc(_c.fd_set.TO, flavor='raw') _c.FD_ZERO(ll_excl) for i in excl: _c.FD_SET(i, ll_excl) if i > nfds: nfds = i else: ll_excl = lltype.nullptr(_c.fd_set.TO) if timeout != -1.0: ll_timeval = rffi.make(_c.timeval) rffi.setintfield(ll_timeval, 'c_tv_sec', int(timeout)) rffi.setintfield(ll_timeval, 'c_tv_usec', int((timeout-int(timeout)) * 1000000)) else: ll_timeval = lltype.nullptr(_c.timeval) try: res = _c.select(nfds + 1, ll_inl, ll_outl, ll_excl, ll_timeval) if res == -1: raise SelectError(_c.geterrno()) if res == 0: return ([], [], []) else: return ( [i for i in inl if _c.FD_ISSET(i, ll_inl)], [i for i in outl if _c.FD_ISSET(i, ll_outl)], [i for i in excl if _c.FD_ISSET(i, ll_excl)]) finally: if ll_inl: lltype.free(ll_inl, flavor='raw') if ll_outl: lltype.free(ll_outl, flavor='raw') if ll_excl: lltype.free(ll_excl, flavor='raw') if ll_timeval: lltype.free(ll_timeval, flavor='raw')
def __init__(self, space): self.space = space self.w_socket = None self.ctx = lltype.nullptr(SSL_CTX_P.TO) self.ssl = lltype.nullptr(SSL_P.TO) self.server_cert = lltype.nullptr(X509_P.TO) self._server = lltype.malloc(rffi.CCHARP.TO, X509_NAME_MAXLEN, flavor='raw') self._server[0] = '\0' self._issuer = lltype.malloc(rffi.CCHARP.TO, X509_NAME_MAXLEN, flavor='raw') self._issuer[0] = '\0'
def test_cast(self): def llfn(v): return rffi.cast(rffi.VOIDP, v) res = self.interpret(llfn, [r_ulonglong(0)]) assert res == lltype.nullptr(rffi.VOIDP.TO) def llfn(v): return rffi.cast(rffi.LONGLONG, v) res = self.interpret(llfn, [lltype.nullptr(rffi.VOIDP.TO)]) assert res == 0 assert isinstance(res, r_longlong)
def do_recv_string(self, space, buflength, maxlength): from pypy.module._multiprocessing.interp_win32 import ( _ReadFile, _PeekNamedPipe, ERROR_BROKEN_PIPE, ERROR_MORE_DATA, ) from pypy.rlib import rwin32 from pypy.interpreter.error import wrap_windowserror read_ptr = lltype.malloc(rffi.CArrayPtr(rwin32.DWORD).TO, 1, flavor="raw") left_ptr = lltype.malloc(rffi.CArrayPtr(rwin32.DWORD).TO, 1, flavor="raw") try: result = _ReadFile(self.handle, self.buffer, min(self.BUFFER_SIZE, buflength), read_ptr, rffi.NULL) if result: return read_ptr[0], lltype.nullptr(rffi.CCHARP.TO) err = rwin32.GetLastError() if err == ERROR_BROKEN_PIPE: raise OperationError(space.w_EOFError, space.w_None) elif err != ERROR_MORE_DATA: raise wrap_windowserror(space, WindowsError(err, "_ReadFile")) # More data... if not _PeekNamedPipe( self.handle, rffi.NULL, 0, lltype.nullptr(rwin32.LPDWORD.TO), lltype.nullptr(rwin32.LPDWORD.TO), left_ptr, ): raise wrap_windowserror(space, rwin32.lastWindowsError()) length = intmask(read_ptr[0] + left_ptr[0]) if length > maxlength: # bad message, close connection self.flags &= ~READABLE if self.flags == 0: self.close() raise OperationError(space.w_IOError, space.wrap("bad message length")) newbuf = lltype.malloc(rffi.CCHARP.TO, length + 1, flavor="raw") for i in range(read_ptr[0]): newbuf[i] = self.buffer[i] result = _ReadFile(self.handle, rffi.ptradd(newbuf, read_ptr[0]), left_ptr[0], read_ptr, rffi.NULL) if not result: rffi.free_charp(newbuf) raise wrap_windowserror(space, rwin32.lastWindowsError()) assert read_ptr[0] == left_ptr[0] return length, newbuf finally: lltype.free(read_ptr, flavor="raw") lltype.free(left_ptr, flavor="raw")
def _ll_dict_del(d, i): d.entries.mark_deleted(i) d.num_items -= 1 # clear the key and the value if they are GC pointers ENTRIES = lltype.typeOf(d.entries).TO ENTRY = ENTRIES.OF entry = d.entries[i] if ENTRIES.must_clear_key: entry.key = lltype.nullptr(ENTRY.key.TO) if ENTRIES.must_clear_value: entry.value = lltype.nullptr(ENTRY.value.TO)
def main(which, x, y): xy1 = lltype.malloc(XY) xy1.vable_access = lltype.nullptr(XY_ACCESS) xy2 = lltype.malloc(XY) xy2.vable_access = lltype.nullptr(XY_ACCESS) xy1.x = x xy1.y = y xy2.x = y xy2.y = x xy = f(which, xy1, xy2) assert xy is xy1 or xy is xy2 return xy.x + xy.y
def __del__(self): if self.ll_args: argnum = len(self.argtypes) for i in range(argnum): if self.ll_args[i]: lltype.free(self.ll_args[i], flavor='raw') lltype.free(self.ll_args, flavor='raw') self.ll_args = lltype.nullptr(rffi.VOIDPP.TO) if self.ll_result: lltype.free(self.ll_result, flavor='raw') self.ll_result = lltype.nullptr(rffi.VOIDP.TO) AbstractFuncPtr.__del__(self)
def set_vable(self, llops, vinst, force_cast=False): if self.top_of_virtualizable_hierarchy: if force_cast: vinst = llops.genop('cast_pointer', [vinst], resulttype=self) for name, llvalue in (('access', lltype.nullptr(self.ACCESS)), ('base', llmemory.NULL), ('rti', lltype.nullptr(VABLERTIPTR.TO))): cname = inputconst(lltype.Void, 'vable_'+name) vvalue = inputconst(lltype.typeOf(llvalue), llvalue) llops.genop('setfield', [vinst, cname, vvalue]) else: self.rbase.set_vable(llops, vinst, force_cast=True)
def __init__(self): self.commitMode = roci.OCI_DEFAULT self.environment = None self.autocommit = False self.sessionHandle = lltype.nullptr(roci.OCISession.TO) self.serverHandle = lltype.nullptr(roci.OCIServer.TO) self.w_inputTypeHandler = None self.w_outputTypeHandler = None self.w_version = None self.release = False
def _ll_dict_del(d, i): d.entries.mark_deleted(i) d.num_items -= 1 # clear the key and the value if they are GC pointers ENTRIES = lltype.typeOf(d.entries).TO ENTRY = ENTRIES.OF entry = d.entries[i] if ENTRIES.must_clear_key: entry.key = lltype.nullptr(ENTRY.key.TO) if ENTRIES.must_clear_value: entry.value = lltype.nullptr(ENTRY.value.TO) num_entries = len(d.entries) if num_entries > DICT_INITSIZE and d.num_items < num_entries / 4: ll_dict_resize(d)
def f(n): while n > 0: myjitdriver.can_enter_jit(n=n) myjitdriver.jit_merge_point(n=n) xy = XY() xy.next1 = lltype.malloc(A, 0) xy.next2 = lltype.malloc(A, 0) xy.next3 = lltype.malloc(A, 0) xy.next4 = lltype.malloc(A, 0) xy.next5 = lltype.malloc(A, 0) xy.n = n exctx.topframeref = vref = virtual_ref(xy) if n % 6 == 0: xy.next1 = lltype.nullptr(A) xy.next2 = lltype.nullptr(A) xy.next3 = lltype.nullptr(A) externalfn(n) n -= 1 exctx.topframeref = vref_None xy.next1 = lltype.nullptr(A) xy.next2 = lltype.nullptr(A) xy.next3 = lltype.nullptr(A) xy.next4 = lltype.nullptr(A) xy.next5 = lltype.nullptr(A) virtual_ref_finish(vref, xy) return exctx.m
def f(x): hint(None, global_merge_point=True) xy = lltype.malloc(XY) xy.vable_access = lltype.nullptr(XY_ACCESS) xy.x = x xy.y = 11 g(xy) x = xy_get_x(xy) y = xy_get_y(xy) return x * 2 + y
def test_latin1(self, space, api): s = 'abcdefg' data = rffi.str2charp(s) w_u = api.PyUnicode_DecodeLatin1(data, len(s), lltype.nullptr(rffi.CCHARP.TO)) assert space.eq_w(w_u, space.wrap(u"abcdefg")) rffi.free_charp(data) uni = u'abcdefg' data = rffi.unicode2wcharp(uni) w_s = api.PyUnicode_EncodeLatin1(data, len(uni), lltype.nullptr(rffi.CCHARP.TO)) assert space.eq_w(space.wrap("abcdefg"), w_s) rffi.free_wcharp(data) ustr = "abcdef" w_ustr = space.wrap(ustr.decode("ascii")) result = api.PyUnicode_AsLatin1String(w_ustr) assert space.eq_w(space.wrap(ustr), result)
class AbstractFuncPtr(object): ll_cif = lltype.nullptr(FFI_CIFP.TO) ll_argtypes = lltype.nullptr(FFI_TYPE_PP.TO) _immutable_fields_ = ['argtypes', 'restype'] def __init__(self, name, argtypes, restype, flags=FUNCFLAG_CDECL): self.name = name self.argtypes = argtypes self.restype = restype self.flags = flags argnum = len(argtypes) self.ll_argtypes = lltype.malloc(FFI_TYPE_PP.TO, argnum, flavor='raw', track_allocation=False) # freed by the __del__ for i in range(argnum): self.ll_argtypes[i] = argtypes[i] self.ll_cif = lltype.malloc(FFI_CIFP.TO, flavor='raw', track_allocation=False) # freed by the __del__ if _MSVC: # This little trick works correctly with MSVC. # It returns small structures in registers if intmask(restype.c_type) == FFI_TYPE_STRUCT: if restype.c_size <= 4: restype = ffi_type_sint32 elif restype.c_size <= 8: restype = ffi_type_sint64 res = c_ffi_prep_cif(self.ll_cif, rffi.cast(rffi.USHORT, get_call_conv(flags,False)), rffi.cast(rffi.UINT, argnum), restype, self.ll_argtypes) if not res == FFI_OK: raise OSError(-1, "Wrong typedef") def __del__(self): if self.ll_cif: lltype.free(self.ll_cif, flavor='raw', track_allocation=False) self.ll_cif = lltype.nullptr(FFI_CIFP.TO) if self.ll_argtypes: lltype.free(self.ll_argtypes, flavor='raw', track_allocation=False) self.ll_argtypes = lltype.nullptr(FFI_TYPE_PP.TO)
def semlock_acquire(self, space, block, w_timeout): if not block: deadline = lltype.nullptr(TIMESPECP.TO) elif space.is_w(w_timeout, space.w_None): deadline = lltype.nullptr(TIMESPECP.TO) else: timeout = space.float_w(w_timeout) sec = int(timeout) nsec = int(1e9 * (timeout - sec) + 0.5) now_sec, now_usec = gettimeofday() deadline = lltype.malloc(TIMESPECP.TO, 1, flavor='raw') rffi.setintfield(deadline[0], 'c_tv_sec', now_sec + sec) rffi.setintfield(deadline[0], 'c_tv_nsec', now_usec * 1000 + nsec) val = rffi.getintfield(deadline[0], 'c_tv_sec') + \ rffi.getintfield(deadline[0], 'c_tv_nsec') / 1000000000 rffi.setintfield(deadline[0], 'c_tv_sec', val) val = rffi.getintfield(deadline[0], 'c_tv_nsec') % 1000000000 rffi.setintfield(deadline[0], 'c_tv_nsec', val) try: while True: try: if not block: sem_trywait(self.handle) elif not deadline: sem_wait(self.handle) else: sem_timedwait(self.handle, deadline) except OSError, e: if e.errno == errno.EINTR: # again continue elif e.errno in (errno.EAGAIN, errno.ETIMEDOUT): return False raise _check_signals(space) return True finally: if deadline: lltype.free(deadline, flavor='raw')
def _internalExecute(self, space, numIters): if self.connection.autocommit: mode = roci.OCI_COMMIT_ON_SUCCESS else: mode = roci.OCI_DEFAULT status = roci.OCIStmtExecute( self.connection.handle, self.handle, self.environment.errorHandle, numIters, 0, lltype.nullptr(roci.OCISnapshot.TO), lltype.nullptr(roci.OCISnapshot.TO), mode) try: self.environment.checkForError( status, "Cursor_InternalExecute()") except OperationError, e: self._setErrorOffset(space, e) raise
def PyEval_SaveThread(space): """Release the global interpreter lock (if it has been created and thread support is enabled) and reset the thread state to NULL, returning the previous thread state. If the lock has been created, the current thread must have acquired it. (This function is available even when thread support is disabled at compile time.)""" state = space.fromcache(InterpreterState) if rffi.aroundstate.before: rffi.aroundstate.before() tstate = state.swap_thread_state(space, lltype.nullptr(PyThreadState.TO)) return tstate
def f(x, y): xy = lltype.malloc(XY) xy.vable_access = lltype.nullptr(XY_ACCESS) xy.x = x xy.y = y e = lltype.malloc(E) e.xy = xy y = xy_get_y(xy) newy = 2 * y xy_set_y(xy, newy) return e
def test_unwrap(): S = lltype.GcStruct('S') RS = lltype.Struct('S') p = lltype.malloc(S) po = lltype.cast_opaque_ptr(llmemory.GCREF, p) assert unwrap(lltype.Void, BoxInt(42)) is None assert unwrap(lltype.Signed, BoxInt(42)) == 42 assert unwrap(lltype.Char, BoxInt(42)) == chr(42) assert unwrap(lltype.Float, boxfloat(42.5)) == 42.5 assert unwrap(lltype.Ptr(S), BoxPtr(po)) == p assert unwrap(lltype.Ptr(RS), BoxInt(0)) == lltype.nullptr(RS)
def get_rpy_roots(gc): count = _do_count_rpy_roots(gc) extra = 16 while True: result = [lltype.nullptr(llmemory.GCREF.TO)] * (count + extra) try: _do_append_rpy_roots(gc, result) except ValueError: extra *= 3 else: return result
def ll_dict_delitem(d, key): i = ll_dict_lookup(d, key, d.keyhash(key)) if not d.entries.valid(i): raise KeyError d.entries.mark_deleted(i) d.num_items -= 1 # clear the key and the value if they are GC pointers ENTRIES = lltype.typeOf(d.entries).TO ENTRY = ENTRIES.OF entry = d.entries[i] if ENTRIES.must_clear_key: key = entry.key # careful about destructor side effects: # keep key alive until entry.value has also # been zeroed (if it must be) entry.key = lltype.nullptr(ENTRY.key.TO) if ENTRIES.must_clear_value: entry.value = lltype.nullptr(ENTRY.value.TO) num_entries = len(d.entries) if num_entries > DICT_INITSIZE and d.num_items < num_entries / 4: ll_dict_resize(d)
def alloc(map_size): null = lltype.nullptr(rffi.VOIDP.TO) res = VirtualAlloc(null, map_size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE) if not res: raise MemoryError arg = lltype.malloc(LPDWORD.TO, 1, zero=True, flavor='raw') VirtualProtect(res, map_size, PAGE_EXECUTE_READWRITE, arg) lltype.free(arg, flavor='raw') # ignore errors, just try return res
def test_const_ptr_subops(): x = """ [p0] guard_class(p0, ConstClass(vtable)) [] """ S = lltype.Struct('S') vtable = lltype.nullptr(S) loop = parse(x, None, locals()) assert len(loop.operations) == 1 assert loop.operations[0].descr assert loop.operations[0].fail_args == []
def ExpandEnvironmentStrings(source): with rffi.scoped_unicode2wcharp(source) as src_buf: size = _ExpandEnvironmentStringsW(src_buf, lltype.nullptr(rffi.CWCHARP.TO), 0) if size == 0: raise rwin32.lastWindowsError("ExpandEnvironmentStrings") size = intmask(size) with rffi.scoped_alloc_unicodebuffer(size) as dest_buf: if _ExpandEnvironmentStringsW(src_buf, dest_buf.raw, size) == 0: raise rwin32.lastWindowsError("ExpandEnvironmentStrings") return dest_buf.str(size - 1) # remove trailing \0
def test_Concat(self, space, api): ref = make_ref(space, space.wrap('abc')) ptr = lltype.malloc(PyObjectP.TO, 1, flavor='raw') ptr[0] = ref api.PyString_Concat(ptr, space.wrap('def')) assert space.str_w(from_ref(space, ptr[0])) == 'abcdef' api.PyString_Concat(ptr, space.w_None) assert not ptr[0] ptr[0] = lltype.nullptr(PyObject.TO) api.PyString_Concat(ptr, space.wrap('def')) # should not crash lltype.free(ptr, flavor='raw')
def unwrapper(space, *args): from pypy.module.cpyext.pyobject import Py_DecRef from pypy.module.cpyext.pyobject import make_ref, from_ref from pypy.module.cpyext.pyobject import Reference newargs = () to_decref = [] assert len(args) == len(api_function.argtypes) for i, (ARG, is_wrapped) in types_names_enum_ui: input_arg = args[i] if is_PyObject(ARG) and not is_wrapped: # build a reference if input_arg is None: arg = lltype.nullptr(PyObject.TO) elif isinstance(input_arg, W_Root): ref = make_ref(space, input_arg) to_decref.append(ref) arg = rffi.cast(ARG, ref) else: arg = input_arg elif is_PyObject(ARG) and is_wrapped: # convert to a wrapped object if input_arg is None: arg = input_arg elif isinstance(input_arg, W_Root): arg = input_arg else: arg = from_ref(space, rffi.cast(PyObject, input_arg)) else: arg = input_arg newargs += (arg, ) try: try: res = func(space, *newargs) except OperationError, e: if not catch_exception: raise if not hasattr(api_function, "error_value"): raise state = space.fromcache(State) state.set_exception(e) if is_PyObject(restype): return None else: return api_function.error_value if not we_are_translated(): got_integer = isinstance(res, (int, long, float)) assert got_integer == expect_integer if res is None: return None elif isinstance(res, Reference): return res.get_wrapped(space) else: return res
def alloc_buffer(count): """ Returns a (raw_buffer, gc_buffer) pair, 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. """ raw_buf = lltype.malloc(TYPEP.TO, count, flavor='raw') return raw_buf, lltype.nullptr(STRTYPE)
def test_weakref(): S1 = lltype.GcStruct('S1', ('x', lltype.Signed)) S = lltype.GcStruct('S', ('s1', S1)) s = lltype.malloc(S) s1 = lltype.cast_pointer(lltype.Ptr(S1), s) w = weakref_create(s) assert weakref_deref(lltype.Ptr(S), w) == s assert weakref_deref(lltype.Ptr(S1), w) == s1 # check that the weakref stays alive even if there are only # cast_pointer'ed references around del s import gc gc.collect() assert weakref_deref(lltype.Ptr(S1), w) == s1 # now really kill the structure del s1 import gc gc.collect() assert weakref_deref(lltype.Ptr(S), w) == lltype.nullptr(S) assert weakref_deref(lltype.Ptr(S1), w) == lltype.nullptr(S1)
class AbstractFuncPtr(object): ll_cif = lltype.nullptr(FFI_CIFP.TO) ll_argtypes = lltype.nullptr(FFI_TYPE_PP.TO) def __init__(self, name, argtypes, restype, flags=0): self.name = name self.argtypes = argtypes self.restype = restype argnum = len(argtypes) self.ll_argtypes = lltype.malloc(FFI_TYPE_PP.TO, argnum, flavor='raw') for i in range(argnum): self.ll_argtypes[i] = argtypes[i] self.ll_cif = lltype.malloc(FFI_CIFP.TO, flavor='raw') if _MS_WINDOWS and (flags & FUNCFLAG_CDECL == 0): cc = FFI_STDCALL else: cc = FFI_DEFAULT_ABI if _MS_WINDOWS: # This little trick works correctly with MSVC. # It returns small structures in registers if r_uint(restype.c_type) == FFI_TYPE_STRUCT: if restype.c_size <= 4: restype = ffi_type_sint32 elif restype.c_size <= 8: restype = ffi_type_sint64 res = c_ffi_prep_cif(self.ll_cif, cc, rffi.cast(rffi.UINT, argnum), restype, self.ll_argtypes) if not res == FFI_OK: raise OSError(-1, "Wrong typedef") def __del__(self): if self.ll_cif: lltype.free(self.ll_cif, flavor='raw') self.ll_cif = lltype.nullptr(FFI_CIFP.TO) if self.ll_argtypes: lltype.free(self.ll_argtypes, flavor='raw') self.ll_argtypes = lltype.nullptr(FFI_TYPE_PP.TO)
def convert_const(self, value): if value._identity is _identity_for_ints: config = self.rtyper.annotator.translator.config assert config.translation.taggedpointers, "need to enable tagged pointers to use erase_int" return lltype.cast_int_to_ptr(self.lowleveltype, value._x * 2 + 1) bk = self.rtyper.annotator.bookkeeper s_obj = value._identity.get_input_annotation(bk) r_obj = self.rtyper.getrepr(s_obj) if r_obj.lowleveltype is lltype.Void: return lltype.nullptr(self.lowleveltype.TO) v = r_obj.convert_const(value._x) return lltype.cast_opaque_ptr(self.lowleveltype, v)
def putenv_llimpl(name, value): l_string = rffi.str2charp('%s=%s' % (name, value)) error = rffi.cast(lltype.Signed, os_putenv(l_string)) if error: rffi.free_charp(l_string) raise OSError(rposix.get_errno(), "os_putenv failed") # keep 'l_string' alive - we know that the C library needs it # until the next call to putenv() with the same 'name'. l_oldstring = envkeepalive.byname.get(name, lltype.nullptr(rffi.CCHARP.TO)) envkeepalive.byname[name] = l_string if l_oldstring: rffi.free_charp(l_oldstring)
def __init__(self, gcdescr=None): # '_gcmap' is an array of length '_gcmap_maxlength' of addresses. # '_gcmap_curlength' tells how full the array really is. # The addresses are actually grouped in pairs: # (addr-after-the-CALL-in-assembler, addr-of-the-call-shape). # '_gcmap_deadentries' counts pairs marked dead (2nd item is NULL). # '_gcmap_sorted' is True only if we know the array is sorted. self._gcmap = lltype.nullptr(self.GCMAP_ARRAY) self._gcmap_curlength = 0 self._gcmap_maxlength = 0 self._gcmap_deadentries = 0 self._gcmap_sorted = True
def test_raw_malloc_access(): S = lltype.GcStruct("S", ('x', lltype.Signed)) T = lltype.GcStruct("T", ('y', lltype.Signed), ('s', lltype.Ptr(S))) # regular malloc zeros GC pointers p_t = lltype.malloc(T) assert p_t.s == lltype.nullptr(S) # raw malloc does not p_raw_t = lltype.malloc(T, flavor="raw") py.test.raises(lltype.UninitializedMemoryAccess, "p_raw_t.s") # this sort of raw_malloc too p_raw_t = cast_adr_to_ptr(raw_malloc(sizeof(T)), lltype.Ptr(T)) py.test.raises(lltype.UninitializedMemoryAccess, "p_raw_t.s")
def os_utime_llimpl(path, tp): # NB. this function is specialized; we get one version where # tp is known to be None, and one version where it is known # to be a tuple of 2 floats. if tp is None: error = os_utime(path, lltype.nullptr(UTIMBUFP.TO)) else: actime, modtime = tp error = os_utime_platform(path, actime, modtime) error = rffi.cast(lltype.Signed, error) if error == -1: raise OSError(rposix.get_errno(), "os_utime failed")
def func(depth, dummy): result = lltype.malloc(PATHARRAY, 1 << depth) os.write(2, 'building tree... ') do_call(result, lltype.nullptr(NODE), 0, depth) os.write(2, 'checking tree... ') #from pypy.rpython.lltypesystem.lloperation import llop #llop.debug_view(lltype.Void, result, # llop.gc_x_size_header(lltype.Signed)) for i in range(1 << depth): check(result[i], i, 0, depth) os.write(2, 'ok\n') return 1
def f(x, a, b): xp = lltype.malloc(XP) xp.vable_access = lltype.nullptr(XP_ACCESS) xp.x = x s = lltype.malloc(S) s.a = a s.b = b xp_set_p(xp, s) p = xp_get_p(xp) p.b = p.b * 2 x = xp_get_x(xp) return xp
class ConstPtr(Const): type = REF value = lltype.nullptr(llmemory.GCREF.TO) _attrs_ = ('value', ) def __init__(self, value): assert lltype.typeOf(value) == llmemory.GCREF self.value = value def clonebox(self): return BoxPtr(self.value) nonconstbox = clonebox def getref_base(self): return self.value def getref(self, PTR): return lltype.cast_opaque_ptr(PTR, self.getref_base()) getref._annspecialcase_ = 'specialize:arg(1)' def _get_hash_(self): if self.value: return lltype.identityhash(self.value) else: return 0 def getaddr(self): return llmemory.cast_ptr_to_adr(self.value) def same_constant(self, other): if isinstance(other, ConstPtr): return self.value == other.value return False def nonnull(self): return bool(self.value) _getrepr_ = repr_pointer def repr_rpython(self): return repr_rpython(self, 'cp') def _get_str(self): # for debugging only from pypy.rpython.annlowlevel import hlstr from pypy.rpython.lltypesystem import rstr try: return hlstr( lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), self.value)) except lltype.UninitializedMemoryAccess: return '<uninitialized string>'
def markcompactcollect(self, requested_size=0): self.debug_collect_start(requested_size) self.debug_check_consistency() # # Mark alive objects # self.to_see = self.AddressDeque() self.trace_from_roots() self.to_see.delete() # # Prepare new views on the same memory # toaddr = llarena.arena_new_view(self.space) maxnum = self.space_size - (self.free - self.space) maxnum /= BYTES_PER_TID llarena.arena_reserve(self.free, llmemory.sizeof(TID_BACKUP, maxnum)) self.tid_backup = llmemory.cast_adr_to_ptr(self.free, lltype.Ptr(TID_BACKUP)) # # Walk all objects and assign forward pointers in the same order, # also updating all references # self.update_forward_pointers(toaddr, maxnum) if (self.run_finalizers.non_empty() or self.objects_with_finalizers.non_empty()): self.update_run_finalizers() self.update_objects_with_id() self.compact() # self.tid_backup = lltype.nullptr(TID_BACKUP) self.free = self.finaladdr self.next_collect_after = self.next_collection(self.finaladdr - toaddr, self.num_alive_objs, requested_size) # if not translated_to_c(): remaining_size = (toaddr + self.space_size) - self.finaladdr llarena.arena_reset(self.finaladdr, remaining_size, False) llarena.arena_free(self.space) self.space = toaddr # self.debug_check_consistency() self.debug_collect_finish() if self.next_collect_after < 0: raise MemoryError # if self.run_finalizers.non_empty(): self.execute_finalizers() return True # executed some finalizers else: return False # no finalizer executed
def call(self, space, args_w): from pypy.module._rawffi.array import W_ArrayInstance from pypy.module._rawffi.structure import W_StructureInstance from pypy.module._rawffi.structure import W_Structure argnum = len(args_w) if argnum != len(self.argshapes): msg = "Wrong number of arguments: expected %d, got %d" raise operationerrfmt(space.w_TypeError, msg, len(self.argshapes), argnum) args_ll = [] for i in range(argnum): argshape = self.argshapes[i] w_arg = args_w[i] if isinstance(argshape, W_Structure): # argument by value arg = space.interp_w(W_StructureInstance, w_arg) xsize, xalignment = size_alignment(self.ptr.argtypes[i]) if (arg.shape.size != xsize or arg.shape.alignment != xalignment): msg = ("Argument %d should be a structure of size %d and " "alignment %d, " "got instead size %d and alignment %d") raise operationerrfmt(space.w_TypeError, msg, i + 1, xsize, xalignment, arg.shape.size, arg.shape.alignment) else: arg = space.interp_w(W_ArrayInstance, w_arg) if arg.length != 1: msg = ("Argument %d should be an array of length 1, " "got length %d") raise operationerrfmt(space.w_TypeError, msg, i + 1, arg.length) argletter = argshape.itemcode letter = arg.shape.itemcode if letter != argletter: if not (argletter in TYPEMAP_PTR_LETTERS and letter in TYPEMAP_PTR_LETTERS): msg = "Argument %d should be typecode %s, got %s" raise operationerrfmt(space.w_TypeError, msg, i + 1, argletter, letter) args_ll.append(arg.ll_buffer) # XXX we could avoid the intermediate list args_ll try: if self.resshape is not None: result = self.resshape.allocate(space, 1, autofree=True) self.ptr.call(args_ll, result.ll_buffer) return space.wrap(result) else: self.ptr.call(args_ll, lltype.nullptr(rffi.VOIDP.TO)) return space.w_None except StackCheckError, e: raise OperationError(space.w_ValueError, space.wrap(e.message))
def getfullpathname_llimpl(path): nBufferLength = rwin32.MAX_PATH + 1 lpBuffer = lltype.malloc(traits.CCHARP.TO, nBufferLength, flavor='raw') try: res = win32traits.GetFullPathName( path, rffi.cast(rwin32.DWORD, nBufferLength), lpBuffer, lltype.nullptr(win32traits.LPSTRP.TO)) if res == 0: raise rwin32.lastWindowsError("_getfullpathname failed") result = traits.charp2str(lpBuffer) return result finally: lltype.free(lpBuffer, flavor='raw')
def f(n): while n > 0: myjitdriver.can_enter_jit(n=n) myjitdriver.jit_merge_point(n=n) xy = XY() xy.n = n exctx.topframeref = vref = virtual_ref(xy) xy.next1 = lltype.malloc(A, 0) n = exctx.topframeref().n - 1 xy.next1 = lltype.nullptr(A) exctx.topframeref = vref_None virtual_ref_finish(vref, xy) return 1