def f(): buf = newbuffer(frame_t, 2) frame1 = buf.pointer() frame1[0].prev = NULL frame2 = buf.pointer() + 1 frame2[0].prev = frame1 roots = newbuffer(Pointer[void], 5) roots[0] = root1 roots[1] = NULL roots[2] = root2 roots[3] = root3 roots[4] = NULL frame1[0].trace_funcs = cast(roots.pointer(), Pointer[void]) frame2[0].trace_funcs = cast(roots.pointer() + 2, Pointer[void]) tracers = newbuffer(Pointer[void], 5) roots[0] = tracer1 roots[1] = NULL roots[2] = tracer2 roots[3] = tracer3 roots[4] = NULL frame1[0].trace_funcs = cast(tracers.pointer(), Pointer[void]) frame2[0].trace_funcs = cast(tracers.pointer() + 2, Pointer[void])
def memcpy(src, dst, size): """ Copy `size` bytes from `src` to `dst` Note that the memory of src and dst may not overlap! """ src = cast(src, Pointer[int8]) dst = cast(dst, Pointer[int8]) for i in range(size): dst[i] = src[i]
def f(): space = gc.GC(100) a = space.alloc(sizeof(A.type)) b = space.alloc(sizeof(B.type)) a = cast(a, type_a) b = cast(b, type_b) a.left = b a.right = 9 b.value = 10
def copy(self, obj, size): """ Copy the object (excluding its children!) to the tospace. This writes a forwarding pointer in the fromspace after having copied the object, and remembers doing so by writing a bit in the forwarding table corresponding to the offset of the object. We could determine the forwarding address for any object that has pointers using the type, for instance by overwriting the first pointer in the object with the new pointer, and checking in which address space that pointer points. However, we support tagless representations, and we may not have any reference, like a mutable value with only integers. We cannot safely determine whether an overwritten location is a forwarding address, or actually a value that happens to fall in the range of the to-space. """ dst_obj = self.tospace.alloc(size, type) memcpy(obj, dst_obj, size) forward_ptr_ptr = cast(obj, Pointer[Pointer[int8]]) forward_ptr_ptr[0] = dst_obj self.forwarding_table.mark(self.offset(obj)) return dst_obj
def align_pointer(p, alignment): "Align pointer memory on a given boundary" i = p.ptrtoint() offset = i % alignment if offset > 0: i += alignment - offset return cast(i, Pointer[int8])
def alloc(self, size): obj = self.offset new_offset = align_pointer(obj + size, 8) if new_offset > self.top(): return cast(0, Pointer[int8]) self.offset = new_offset return obj
def trace(self, obj, size, trace_children): """ Mark the reachable object. We first check if the object is already copied, in which case we're done. Otherwise, we copy the object to the tospace, and we trace the children. The copy operation will mark the object as copied in the forwarding table. We call __flypy_trace__ to mark GC-tracked children. This method is automatically generated, and allows us to avoid type tagging values to determine pointer locations. It also patches pointers to copied objects. """ #assert self.fromspace.bottom() <= obj < self.fromspace.top if self.forwarded(obj): # Object already copied, use forwarding pointer forward_ptr_ptr = cast(obj, Pointer[Pointer[int8]]) dst_obj = forward_ptr_ptr[0] return dst_obj copied_obj = self.copy(obj, size) trace_children(copied_obj) return copied_obj
def f(): p = ffi.malloc(cast(2, types.int64), types.int32) p[0] = 4 p[1] = 5 return p
def mark(self, pos): """Mark the bit at `pos`""" byte = 1 << self._bitpos(pos) byte = cast(byte, types.int8) self.buf[self._bytepos(pos)] |= byte
def unmark(self, pos): """Unmark the bit at `pos`""" byte = ~(1 << self._bitpos(pos)) byte = cast(byte, types.int8) self.buf[self._bytepos(pos)] &= byte
def clear(self): """Clear the bit vector""" self.buf[:] = cast(0, types.int8)
def coerce(x, ty): return cast(x, ty)
def f(x, dst_type): return cast(x, dst_type)