11#include <stdio.h>
22#include <string.h>
3+ #include <stdbool.h>
34
45#include "mpconfig.h"
56#include "misc.h"
67#include "gc.h"
78
9+ #include "misc.h"
10+ #include "qstr.h"
11+ #include "obj.h"
12+ #include "runtime.h"
13+
814#if MICROPY_ENABLE_GC
915
1016#if 0 // print debugging info
@@ -21,7 +27,9 @@ typedef unsigned char byte;
2127#define STACK_SIZE (64) // tunable; minimum is 1
2228
2329STATIC byte * gc_alloc_table_start ;
30+ STATIC byte * gc_mpobj_table_start ;
2431STATIC machine_uint_t gc_alloc_table_byte_len ;
32+ STATIC machine_uint_t gc_mpobj_table_byte_len ;
2533STATIC machine_uint_t * gc_pool_start ;
2634STATIC machine_uint_t * gc_pool_end ;
2735
@@ -59,6 +67,10 @@ STATIC machine_uint_t *gc_sp;
5967#define ATB_HEAD_TO_MARK (block ) do { gc_alloc_table_start[(block) / BLOCKS_PER_ATB] |= (AT_MARK << BLOCK_SHIFT(block)); } while (0)
6068#define ATB_MARK_TO_HEAD (block ) do { gc_alloc_table_start[(block) / BLOCKS_PER_ATB] &= (~(AT_TAIL << BLOCK_SHIFT(block))); } while (0)
6169
70+ #define ATB_SET_MPOBJ (block ) do { gc_mpobj_table_start[(block) / 8] |= (1<<(block%8)); } while (0)
71+ #define ATB_CLR_MPOBJ (block ) do { gc_mpobj_table_start[(block) / 8] &= (~(1<<(block%8))); } while (0)
72+ #define ATB_IS_MPOBJ (block ) ((gc_mpobj_table_start[(block) / 8]>>(block%8))&0x01)
73+
6274#define BLOCK_FROM_PTR (ptr ) (((ptr) - (machine_uint_t)gc_pool_start) / BYTES_PER_BLOCK)
6375#define PTR_FROM_BLOCK (block ) (((block) * BYTES_PER_BLOCK + (machine_uint_t)gc_pool_start))
6476#define ATB_FROM_BLOCK (bl ) ((bl) / BLOCKS_PER_ATB)
@@ -73,14 +85,21 @@ void gc_init(void *start, void *end) {
7385 machine_uint_t total_word_len = (machine_uint_t * )end - (machine_uint_t * )start ;
7486 gc_alloc_table_byte_len = total_word_len * BYTES_PER_WORD / (1 + BITS_PER_BYTE / 2 * BYTES_PER_BLOCK );
7587 gc_alloc_table_start = (byte * )start ;
76- machine_uint_t gc_pool_block_len = gc_alloc_table_byte_len * BITS_PER_BYTE / 2 ;
88+
89+ gc_mpobj_table_byte_len = (gc_alloc_table_byte_len * BITS_PER_BYTE / 2 )/8 ;
90+ gc_mpobj_table_start = gc_alloc_table_start + gc_alloc_table_byte_len ;
91+
92+ machine_uint_t gc_pool_block_len = (gc_alloc_table_byte_len * BITS_PER_BYTE / 2 ) - (gc_mpobj_table_byte_len / BYTES_PER_BLOCK );
7793 machine_uint_t gc_pool_word_len = gc_pool_block_len * WORDS_PER_BLOCK ;
7894 gc_pool_start = (machine_uint_t * )end - gc_pool_word_len ;
7995 gc_pool_end = end ;
8096
8197 // clear ATBs
8298 memset (gc_alloc_table_start , 0 , gc_alloc_table_byte_len );
8399
100+ // clear MPOBJ flags
101+ memset (gc_mpobj_table_start , 0 , gc_mpobj_table_byte_len );
102+
84103 // allocate first block because gc_pool_start points there and it will never
85104 // be freed, so allocating 1 block with null pointers will minimise memory loss
86105 ATB_FREE_TO_HEAD (0 );
@@ -157,6 +176,16 @@ STATIC void gc_sweep(void) {
157176 for (machine_uint_t block = 0 ; block < gc_alloc_table_byte_len * BLOCKS_PER_ATB ; block ++ ) {
158177 switch (ATB_GET_KIND (block )) {
159178 case AT_HEAD :
179+ if (ATB_IS_MPOBJ (block )) {
180+ mp_obj_t dest [2 ];
181+ mp_load_method ((mp_obj_t * )PTR_FROM_BLOCK (block ), MP_QSTR___del__ , dest );
182+ // load_method returned a method
183+ if (dest [1 ] != MP_OBJ_NULL ) {
184+ mp_call_method_n_kw (0 , 0 , dest );
185+ }
186+ // clear mpobj flag
187+ ATB_CLR_MPOBJ (block );
188+ }
160189 free_tail = 1 ;
161190 // fall through to free the head
162191
@@ -237,7 +266,7 @@ void gc_info(gc_info_t *info) {
237266 info -> free *= BYTES_PER_BLOCK ;
238267}
239268
240- void * gc_alloc (machine_uint_t n_bytes ) {
269+ void * _gc_alloc (machine_uint_t n_bytes , bool is_mpobj ) {
241270 machine_uint_t n_blocks = ((n_bytes + BYTES_PER_BLOCK - 1 ) & (~(BYTES_PER_BLOCK - 1 ))) / BYTES_PER_BLOCK ;
242271 DEBUG_printf ("gc_alloc(" UINT_FMT " bytes -> " UINT_FMT " blocks)\n" , n_bytes , n_blocks );
243272
@@ -286,10 +315,23 @@ void *gc_alloc(machine_uint_t n_bytes) {
286315 ATB_FREE_TO_TAIL (bl );
287316 }
288317
318+ if (is_mpobj ) {
319+ // set mp_obj flag only if it has del
320+ ATB_SET_MPOBJ (start_block );
321+ }
322+
289323 // return pointer to first block
290324 return (void * )(gc_pool_start + start_block * WORDS_PER_BLOCK );
291325}
292326
327+ void * gc_alloc (machine_uint_t n_bytes ) {
328+ return _gc_alloc (n_bytes , false);
329+ }
330+
331+ void * gc_alloc_mp_obj (machine_uint_t n_bytes ) {
332+ return _gc_alloc (n_bytes , true);
333+ }
334+
293335// force the freeing of a piece of memory
294336void gc_free (void * ptr_in ) {
295337 machine_uint_t ptr = (machine_uint_t )ptr_in ;
0 commit comments