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)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy