11#include <stdio.h>
22#include <string.h>
3+ #include <stdbool.h>
34
45#include "mpconfig.h"
56#include "gc.h"
67
8+ #include "misc.h"
9+ #include "qstr.h"
10+ #include "obj.h"
11+
712#if MICROPY_ENABLE_GC
813
914#if 0 // print debugging info
@@ -20,7 +25,9 @@ typedef unsigned char byte;
2025#define STACK_SIZE (64) // tunable; minimum is 1
2126
2227STATIC byte * gc_alloc_table_start ;
28+ STATIC byte * gc_mpobj_table_start ;
2329STATIC machine_uint_t gc_alloc_table_byte_len ;
30+ STATIC machine_uint_t gc_mpobj_table_byte_len ;
2431STATIC machine_uint_t * gc_pool_start ;
2532STATIC machine_uint_t * gc_pool_end ;
2633
@@ -58,6 +65,10 @@ STATIC machine_uint_t *gc_sp;
5865#define ATB_HEAD_TO_MARK (block ) do { gc_alloc_table_start[(block) / BLOCKS_PER_ATB] |= (AT_MARK << BLOCK_SHIFT(block)); } while (0)
5966#define ATB_MARK_TO_HEAD (block ) do { gc_alloc_table_start[(block) / BLOCKS_PER_ATB] &= (~(AT_TAIL << BLOCK_SHIFT(block))); } while (0)
6067
68+ #define ATB_SET_MPOBJ (block ) do { gc_mpobj_table_start[(block) / 8] |= (1<<(block%8)); } while (0)
69+ #define ATB_CLR_MPOBJ (block ) do { gc_mpobj_table_start[(block) / 8] &= (~(1<<(block%8))); } while (0)
70+ #define ATB_IS_MPOBJ (block ) ((gc_mpobj_table_start[(block) / 8]>>(block%8))&0x01)
71+
6172#define BLOCK_FROM_PTR (ptr ) (((ptr) - (machine_uint_t)gc_pool_start) / BYTES_PER_BLOCK)
6273#define PTR_FROM_BLOCK (block ) (((block) * BYTES_PER_BLOCK + (machine_uint_t)gc_pool_start))
6374#define ATB_FROM_BLOCK (bl ) ((bl) / BLOCKS_PER_ATB)
@@ -72,14 +83,21 @@ void gc_init(void *start, void *end) {
7283 machine_uint_t total_word_len = (machine_uint_t * )end - (machine_uint_t * )start ;
7384 gc_alloc_table_byte_len = total_word_len * BYTES_PER_WORD / (1 + BITS_PER_BYTE / 2 * BYTES_PER_BLOCK );
7485 gc_alloc_table_start = (byte * )start ;
75- machine_uint_t gc_pool_block_len = gc_alloc_table_byte_len * BITS_PER_BYTE / 2 ;
86+
87+ gc_mpobj_table_byte_len = (gc_alloc_table_byte_len * BITS_PER_BYTE / 2 )/8 ;
88+ gc_mpobj_table_start = gc_alloc_table_start + gc_alloc_table_byte_len ;
89+
90+ machine_uint_t gc_pool_block_len = (gc_alloc_table_byte_len * BITS_PER_BYTE / 2 ) - (gc_mpobj_table_byte_len / BYTES_PER_BLOCK );
7691 machine_uint_t gc_pool_word_len = gc_pool_block_len * WORDS_PER_BLOCK ;
7792 gc_pool_start = (machine_uint_t * )end - gc_pool_word_len ;
7893 gc_pool_end = end ;
7994
8095 // clear ATBs
8196 memset (gc_alloc_table_start , 0 , gc_alloc_table_byte_len );
8297
98+ // clear MPOBJ flags
99+ memset (gc_mpobj_table_start , 0 , gc_mpobj_table_byte_len );
100+
83101 // allocate first block because gc_pool_start points there and it will never
84102 // be freed, so allocating 1 block with null pointers will minimise memory loss
85103 ATB_FREE_TO_HEAD (0 );
@@ -156,6 +174,14 @@ STATIC void gc_sweep(void) {
156174 for (machine_uint_t block = 0 ; block < gc_alloc_table_byte_len * BLOCKS_PER_ATB ; block ++ ) {
157175 switch (ATB_GET_KIND (block )) {
158176 case AT_HEAD :
177+ if (ATB_IS_MPOBJ (block )) {
178+ ATB_CLR_MPOBJ (block ); // clear mpobj flag
179+ mp_obj_t * self = (mp_obj_t * )PTR_FROM_BLOCK (block );
180+ mp_obj_type_t * type = mp_obj_get_type (self );
181+ if (type -> del != NULL ) {
182+ type -> del (self );
183+ }
184+ }
159185 free_tail = 1 ;
160186 // fall through to free the head
161187
@@ -236,7 +262,7 @@ void gc_info(gc_info_t *info) {
236262 info -> free *= BYTES_PER_BLOCK ;
237263}
238264
239- void * gc_alloc (machine_uint_t n_bytes ) {
265+ void * _gc_alloc (machine_uint_t n_bytes , bool is_mpobj ) {
240266 machine_uint_t n_blocks = ((n_bytes + BYTES_PER_BLOCK - 1 ) & (~(BYTES_PER_BLOCK - 1 ))) / BYTES_PER_BLOCK ;
241267 DEBUG_printf ("gc_alloc(" UINT_FMT " bytes -> " UINT_FMT " blocks)\n" , n_bytes , n_blocks );
242268
@@ -279,6 +305,10 @@ void *gc_alloc(machine_uint_t n_bytes) {
279305 // mark first block as used head
280306 ATB_FREE_TO_HEAD (start_block );
281307
308+ if (is_mpobj ) {
309+ ATB_SET_MPOBJ (start_block );
310+ }
311+
282312 // mark rest of blocks as used tail
283313 // TODO for a run of many blocks can make this more efficient
284314 for (machine_uint_t bl = start_block + 1 ; bl <= end_block ; bl ++ ) {
@@ -289,6 +319,14 @@ void *gc_alloc(machine_uint_t n_bytes) {
289319 return (void * )(gc_pool_start + start_block * WORDS_PER_BLOCK );
290320}
291321
322+ void * gc_alloc (machine_uint_t n_bytes ) {
323+ return _gc_alloc (n_bytes , false);
324+ }
325+
326+ void * gc_alloc_mp_obj (machine_uint_t n_bytes ) {
327+ return _gc_alloc (n_bytes , true);
328+ }
329+
292330// force the freeing of a piece of memory
293331void gc_free (void * ptr_in ) {
294332 machine_uint_t ptr = (machine_uint_t )ptr_in ;
0 commit comments