Skip to content

Commit d75ff42

Browse files
jeplerdpgeorge
authored andcommitted
unix/coverage: Add extra GC coverage test for ATB gap byte.
The assertion that is added here (to gc.c) fails when running this new test if ALLOC_TABLE_GAP_BYTE is set to 0. Signed-off-by: Jeff Epler <jepler@gmail.com> Signed-off-by: Damien George <damien@micropython.org>
1 parent 9f434dd commit d75ff42

File tree

3 files changed

+42
-0
lines changed

3 files changed

+42
-0
lines changed

ports/unix/coverage.c

Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
#include <stdio.h>
2+
#include <stdlib.h>
23
#include <string.h>
34

45
#include "py/obj.h"
@@ -224,6 +225,42 @@ STATIC mp_obj_t extra_coverage(void) {
224225
mp_printf(&mp_plat_print, "%p\n", gc_nbytes(NULL));
225226
}
226227

228+
// GC initialisation and allocation stress test, to check the logic behind ALLOC_TABLE_GAP_BYTE
229+
// (the following test should fail when ALLOC_TABLE_GAP_BYTE=0)
230+
{
231+
mp_printf(&mp_plat_print, "# GC part 2\n");
232+
233+
// check the GC is unlocked and save its state
234+
assert(MP_STATE_THREAD(gc_lock_depth) == 0);
235+
mp_state_mem_t mp_state_mem_orig = mp_state_ctx.mem;
236+
237+
// perform the test
238+
unsigned heap_size = 64 * MICROPY_BYTES_PER_GC_BLOCK;
239+
for (unsigned j = 0; j < 256 * MP_BYTES_PER_OBJ_WORD; ++j) {
240+
char *heap = calloc(heap_size, 1);
241+
gc_init(heap, heap + heap_size);
242+
243+
m_malloc(MICROPY_BYTES_PER_GC_BLOCK);
244+
void *o = gc_alloc(MICROPY_BYTES_PER_GC_BLOCK, GC_ALLOC_FLAG_HAS_FINALISER);
245+
((mp_obj_base_t *)o)->type = NULL; // ensure type is cleared so GC doesn't look for finaliser
246+
for (unsigned i = 0; i < heap_size / MICROPY_BYTES_PER_GC_BLOCK; ++i) {
247+
void *p = m_malloc_maybe(MICROPY_BYTES_PER_GC_BLOCK);
248+
if (!p) {
249+
break;
250+
}
251+
*(void **)p = o;
252+
o = p;
253+
}
254+
gc_collect();
255+
free(heap);
256+
heap_size += MICROPY_BYTES_PER_GC_BLOCK / 16;
257+
}
258+
mp_printf(&mp_plat_print, "pass\n");
259+
260+
// restore the GC state (the original heap)
261+
mp_state_ctx.mem = mp_state_mem_orig;
262+
}
263+
227264
// tracked allocation
228265
{
229266
#define NUM_PTRS (8)

py/gc.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,9 @@ STATIC void gc_mark_subtree(size_t block)
297297
n_blocks += 1;
298298
} while (ATB_GET_KIND(area, block + n_blocks) == AT_TAIL);
299299

300+
// check that the consecutive blocks didn't overflow past the end of the area
301+
assert(area->gc_pool_start + (block + n_blocks) * BYTES_PER_BLOCK <= area->gc_pool_end);
302+
300303
// check this block's children
301304
void **ptrs = (void **)PTR_FROM_BLOCK(area, block);
302305
for (size_t i = n_blocks * BYTES_PER_BLOCK / sizeof(void *); i > 0; i--, ptrs++) {

tests/unix/extra_coverage.py.exp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@ abc
1717
# GC
1818
0
1919
0
20+
# GC part 2
21+
pass
2022
# tracked allocation
2123
m_tracked_head = 0
2224
0 1

0 commit comments

Comments
 (0)