def allocate_prebuilt_ref(self, size): o = lib.allocate_prebuilt(self.header_size + size * ffi.sizeof("myobject_t *")) self.assertNotEqual(o, ffi.NULL) lib._set_type_id(o, size) lib.qcgc_write(o) # Register object return ffi.cast("myobject_t *", o)
def test_color_transitions(self): """Test all possible color transitions""" reachable = list() unreachable = list() for i in range(2 * lib.QCGC_INC_MARK_MIN): o = self.allocate_ref(1) self.push_root(o) reachable.append(o) self.assertEqual(lib.qcgc_get_mark_color(ffi.cast("object_t *",o)), lib.MARK_COLOR_LIGHT_GRAY) lib.qcgc_incmark() # Marks ALL root objects self.assertEqual(lib.qcgc_state.phase, lib.GC_MARK) for o in reachable: self.assertIn(lib.qcgc_get_mark_color(ffi.cast("object_t *", o)), [lib.MARK_COLOR_DARK_GRAY, lib.MARK_COLOR_BLACK]) if (lib.qcgc_get_mark_color(ffi.cast("object_t *", o)) == lib.MARK_COLOR_BLACK): # Trigger write barrier and add object lib.qcgc_write(ffi.cast("object_t *", o)) self.assertEqual(lib.qcgc_get_mark_color(ffi.cast("object_t *", o)), lib.MARK_COLOR_DARK_GRAY) lib.qcgc_mark() for o in reachable: self.assertEqual(lib.qcgc_get_mark_color(ffi.cast("object_t *", o)), lib.MARK_COLOR_BLACK) lib.bump_ptr_reset() lib.qcgc_sweep() for o in reachable: self.assertEqual(lib.qcgc_get_mark_color(ffi.cast("object_t *", o)), lib.MARK_COLOR_WHITE)
def allocate_weakref(self, to): o = lib.qcgc_allocate(self.header_size + ffi.sizeof("myobject_t *")) self.assertNotEqual(o, ffi.NULL) lib._set_type_id(o, 0) # Prevent from tracing ffi.cast("myobject_t *", o).refs[0] = ffi.cast("myobject_t *", to) # Ref has to be valid before registering lib.qcgc_register_weakref(o, ffi.cast("object_t **", ffi.cast("myobject_t *", o).refs)) # XXX: ffi.addressof .refs[0] does not work lib.qcgc_write(o) return o
def allocate_weakref(self, to): o = lib.qcgc_allocate(self.header_size + ffi.sizeof("myobject_t *")) self.assertNotEqual(o, ffi.NULL) lib._set_type_id(o, 0) # Prevent from tracing ffi.cast("myobject_t *", o).refs[0] = ffi.cast( "myobject_t *", to) # Ref has to be valid before registering lib.qcgc_register_weakref( o, ffi.cast( "object_t **", ffi.cast("myobject_t *", o).refs)) # XXX: ffi.addressof .refs[0] does not work lib.qcgc_write(o) return o
def test_write_barrier(self): o = self.allocate(16) self.push_root(o) arena = lib.qcgc_arena_addr(ffi.cast("cell_t *", o)) o.hdr.flags = o.hdr.flags & ~lib.QCGC_GRAY_FLAG self.assertEqual(ffi.cast("object_t *", o).flags & lib.QCGC_GRAY_FLAG, 0) lib.qcgc_write(ffi.cast("object_t *", o)) self.assertEqual(ffi.cast("object_t *", o).flags & lib.QCGC_GRAY_FLAG, lib.QCGC_GRAY_FLAG) lib.qcgc_state.phase = lib.GC_MARK o = self.allocate(16) self.push_root(o) arena = lib.qcgc_arena_addr(ffi.cast("cell_t *", o)) o.hdr.flags = o.hdr.flags & ~lib.QCGC_GRAY_FLAG self.assertEqual(ffi.cast("object_t *", o).flags & lib.QCGC_GRAY_FLAG, 0) self.set_blocktype(ffi.cast("cell_t *", o), lib.BLOCK_BLACK) lib.qcgc_state.phase = lib.GC_MARK lib.qcgc_write(ffi.cast("object_t *", o)) self.assertEqual(ffi.cast("object_t *", o).flags & lib.QCGC_GRAY_FLAG, lib.QCGC_GRAY_FLAG) self.assertEqual(lib.arena_gray_stack(arena).count, 1) self.assertEqual(lib.arena_gray_stack(arena).items[0], o)
def set_ref(self, obj, index, ref): lib.qcgc_write(ffi.cast("object_t *", obj)) # Trigger write barrier assert index >= 0 assert ffi.cast("myobject_t *", obj).type_id > index ffi.cast("myobject_t *", obj).refs[index] = ffi.cast("myobject_t *", ref)