def test_fit_allocate_no_double_entry(self): roots = list() x = self.bump_allocate(16 * 3) roots.append(x) self.bump_allocate(16 * 1) roots.append(self.bump_allocate(16 * 1)) # for r in roots: self.push_root(r) lib.bump_ptr_reset() lib.qcgc_collect() for _ in roots: self.pop_root() # self.assertEqual(lib.small_free_list(0).count, 1) # del roots[0] for r in roots: self.push_root(r) lib.qcgc_collect() for _ in roots: self.pop_root() # self.assertEqual(lib.small_free_list(3).count, 1) # y = lib.qcgc_fit_allocate(16 * 3) # Create double entry self.assertEqual(lib.small_free_list(3).count, 0) self.assertEqual(lib.small_free_list(0).count, 1) self.assertEqual(x, y)
def test_collected_weakref_no_err(self): alive = self.allocate(1) self.push_root(alive) wr = self.allocate_weakref(alive) # Collect lib.bump_ptr_reset() lib.qcgc_collect()
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 test_bump_remain_allocated(self): for _ in range(10): self.push_root(self.allocate(1)) lib.bump_ptr_reset() lib.qcgc_collect() self.assertEqual(lib.qcgc_state.free_cells, self.arena_blocks - 10) lib.qcgc_collect() self.assertEqual(lib.qcgc_state.free_cells, self.arena_blocks - 10)
def test_reuse_old_free_space(self): arena = lib.qcgc_arena_create() first_cell = lib.arena_cells(arena)[lib.qcgc_arena_first_cell_index] size = lib.qcgc_arena_cells_count - lib.qcgc_arena_first_cell_index lib.qcgc_fit_allocator_add(ffi.addressof(first_cell), size) lib.bump_ptr_reset() p = self.bump_allocate(16) self.assertEqual(ffi.addressof(first_cell), p)
def test_bump_allocate(self): for _ in range(2 ** 9): self.push_root(self.allocate(1)) lib.bump_ptr_reset() lib.qcgc_collect() self.assertEqual(lib.qcgc_state.free_cells, self.arena_blocks - 2 ** 9) self.assertEqual(lib.qcgc_state.largest_free_block, self.arena_blocks - 2 ** 9)
def test_weakref_to_prebuilt(self): prebuilt = self.allocate_prebuilt(1) wr = self.allocate_weakref(prebuilt) self.push_root(wr) # Collect lib.bump_ptr_reset() lib.qcgc_collect() # self.assertEqual(self.get_ref(wr, 0), prebuilt)
def test_write_barrier_after_sweep(self): o = self.allocate_ref(1) self.push_root(o) # lib.qcgc_collect() # p = self.allocate(1) self.set_ref(o, 0, p) # lib.bump_ptr_reset() lib.qcgc_collect() # self.assertIn(self.get_blocktype(ffi.cast("cell_t *", p)), [lib.BLOCK_WHITE, lib.BLOCK_BLACK])
def test_fit_all_free(self): for _ in range(10): self.allocate(1) self.push_root(self.allocate(1)) # Make it non coalesced lib.bump_ptr_reset() lib.qcgc_collect() self.assertEqual(lib.qcgc_state.free_cells, self.arena_blocks - 10) for _ in range(10): self.push_root(lib.qcgc_fit_allocate(1)) lib.qcgc_collect() self.assertEqual(lib.qcgc_state.free_cells, self.arena_blocks - 20)
def test_bump_all_free(self): for _ in range(10): self.push_root(self.allocate(1)) lib.bump_ptr_reset() lib.qcgc_collect() self.assertEqual(lib.qcgc_state.free_cells, self.arena_blocks - 10) # for _ in range(10): self.pop_root() # lib.qcgc_collect() self.assertEqual(lib.qcgc_state.free_cells, 0) # As the arena is free now self.assertEqual(lib.qcgc_state.largest_free_block, 0)
def weakref_to_alive_and_dead(self, alive, dead): """Utility to reduce code duplication in test cases. Client is responsible that alive object remains alive""" wr_to_alive = self.allocate_weakref(alive) wr_to_dead = self.allocate_weakref(dead) self.push_root(wr_to_alive) self.push_root(wr_to_dead) # Collect lib.bump_ptr_reset() lib.qcgc_collect() # self.assertEqual(self.get_ref(wr_to_alive, 0), alive) self.assertEqual(self.get_ref(wr_to_dead, 0), ffi.NULL)
def test_prebuilt(self): p = self.allocate_prebuilt(1) q = self.allocate_prebuilt_ref(4) r = self.allocate(1) s = self.allocate_ref(4) self.set_ref(q, 0, p) self.set_ref(q, 1, q) self.set_ref(q, 2, r) self.set_ref(q, 3, s) self.set_ref(s, 0, p) self.set_ref(s, 1, q) self.set_ref(s, 2, r) self.set_ref(s, 3, s) lib.bump_ptr_reset() lib.qcgc_collect() self.assertEqual(self.get_blocktype(ffi.cast("cell_t *", r)), lib.BLOCK_WHITE) self.assertEqual(self.get_blocktype(ffi.cast("cell_t *", s)), lib.BLOCK_WHITE)
def test_mark_large(self): o = ffi.cast("object_t *", self.allocate(lib.qcgc_arena_size)) self.push_root(o) p = ffi.cast("object_t *", self.allocate_ref(lib.qcgc_arena_size // ffi.sizeof("myobject_t *"))) self.push_root(p) q = ffi.cast("object_t *", self.allocate(lib.qcgc_arena_size)) self.push_root(q) r = ffi.cast("object_t *", self.allocate(1)) self.push_root(r) s = ffi.cast("object_t *", self.allocate_ref(1)) self.push_root(s) t = ffi.cast("object_t *", self.allocate(lib.qcgc_arena_size)) self.push_root(t) self.set_ref(p, 0, q) self.set_ref(p, 1, r) self.set_ref(p, 2, s) self.set_ref(s, 0, p) # for _ in range(6): self.pop_root() self.push_root(o) self.push_root(s) # lib.qcgc_mark() # self.assertTrue(self.hbtable_has(o)) self.assertTrue(self.hbtable_marked(o)) self.assertEqual(lib.qcgc_state.gray_stack_size, 0) # self.assertTrue(self.hbtable_has(p)) self.assertTrue(self.hbtable_marked(p)) self.assertEqual(lib.qcgc_state.gray_stack_size, 0) # self.assertTrue(self.hbtable_has(q)) self.assertTrue(self.hbtable_marked(q)) self.assertEqual(lib.qcgc_state.gray_stack_size, 0) # self.assertTrue(self.hbtable_has(t)) self.assertFalse(self.hbtable_marked(t)) self.assertEqual(lib.qcgc_state.gray_stack_size, 0) # self.assertEqual(self.get_blocktype( ffi.cast("cell_t *", s)), lib.BLOCK_BLACK) self.assertEqual(self.get_blocktype( ffi.cast("cell_t *", r)), lib.BLOCK_BLACK) # lib.bump_ptr_reset() lib.qcgc_sweep() # self.assertTrue(self.hbtable_has(o)) self.assertFalse(self.hbtable_marked(o)) self.assertEqual(lib.qcgc_state.gray_stack_size, 0) # self.assertTrue(self.hbtable_has(p)) self.assertFalse(self.hbtable_marked(p)) self.assertEqual(lib.qcgc_state.gray_stack_size, 0) # self.assertTrue(self.hbtable_has(q)) self.assertFalse(self.hbtable_marked(q)) self.assertEqual(lib.qcgc_state.gray_stack_size, 0) # self.assertFalse(self.hbtable_has(t)) self.assertFalse(self.hbtable_marked(t)) self.assertEqual(lib.qcgc_state.gray_stack_size, 0) # self.assertEqual(self.get_blocktype( ffi.cast("cell_t *", s)), lib.BLOCK_WHITE) self.assertEqual(self.get_blocktype( ffi.cast("cell_t *", r)), lib.BLOCK_WHITE)
def test_mark_large(self): o = ffi.cast("object_t *", self.allocate(lib.qcgc_arena_size)) self.push_root(o) p = ffi.cast( "object_t *", self.allocate_ref(lib.qcgc_arena_size // ffi.sizeof("myobject_t *"))) self.push_root(p) q = ffi.cast("object_t *", self.allocate(lib.qcgc_arena_size)) self.push_root(q) r = ffi.cast("object_t *", self.allocate(1)) self.push_root(r) s = ffi.cast("object_t *", self.allocate_ref(1)) self.push_root(s) t = ffi.cast("object_t *", self.allocate(lib.qcgc_arena_size)) self.push_root(t) self.set_ref(p, 0, q) self.set_ref(p, 1, r) self.set_ref(p, 2, s) self.set_ref(s, 0, p) # for _ in range(6): self.pop_root() self.push_root(o) self.push_root(s) # lib.qcgc_mark() # self.assertTrue(self.hbtable_has(o)) self.assertTrue(self.hbtable_marked(o)) self.assertEqual(lib.qcgc_state.gray_stack_size, 0) # self.assertTrue(self.hbtable_has(p)) self.assertTrue(self.hbtable_marked(p)) self.assertEqual(lib.qcgc_state.gray_stack_size, 0) # self.assertTrue(self.hbtable_has(q)) self.assertTrue(self.hbtable_marked(q)) self.assertEqual(lib.qcgc_state.gray_stack_size, 0) # self.assertTrue(self.hbtable_has(t)) self.assertFalse(self.hbtable_marked(t)) self.assertEqual(lib.qcgc_state.gray_stack_size, 0) # self.assertEqual(self.get_blocktype(ffi.cast("cell_t *", s)), lib.BLOCK_BLACK) self.assertEqual(self.get_blocktype(ffi.cast("cell_t *", r)), lib.BLOCK_BLACK) # lib.bump_ptr_reset() lib.qcgc_sweep() # self.assertTrue(self.hbtable_has(o)) self.assertFalse(self.hbtable_marked(o)) self.assertEqual(lib.qcgc_state.gray_stack_size, 0) # self.assertTrue(self.hbtable_has(p)) self.assertFalse(self.hbtable_marked(p)) self.assertEqual(lib.qcgc_state.gray_stack_size, 0) # self.assertTrue(self.hbtable_has(q)) self.assertFalse(self.hbtable_marked(q)) self.assertEqual(lib.qcgc_state.gray_stack_size, 0) # self.assertFalse(self.hbtable_has(t)) self.assertFalse(self.hbtable_marked(t)) self.assertEqual(lib.qcgc_state.gray_stack_size, 0) # self.assertEqual(self.get_blocktype(ffi.cast("cell_t *", s)), lib.BLOCK_WHITE) self.assertEqual(self.get_blocktype(ffi.cast("cell_t *", r)), lib.BLOCK_WHITE)