@@ -230,6 +230,7 @@ bool gc_is_locked(void) {
230
230
return MP_STATE_THREAD (gc_lock_depth ) != 0 ;
231
231
}
232
232
233
+ #if MICROPY_GC_MULTIHEAP
233
234
// Returns the area to which this pointer belongs, or NULL if it isn't
234
235
// allocated on the GC-managed heap.
235
236
STATIC inline mp_state_mem_area_t * gc_get_ptr_area (const void * ptr ) {
@@ -244,6 +245,14 @@ STATIC inline mp_state_mem_area_t *gc_get_ptr_area(const void *ptr) {
244
245
}
245
246
return NULL ;
246
247
}
248
+ #endif
249
+
250
+ // ptr should be of type void*
251
+ #define VERIFY_PTR (ptr ) ( \
252
+ ((uintptr_t)(ptr) & (BYTES_PER_BLOCK - 1)) == 0 /* must be aligned on a block */ \
253
+ && ptr >= (void *)MP_STATE_MEM(area).gc_pool_start /* must be above start of pool */ \
254
+ && ptr < (void *)MP_STATE_MEM(area).gc_pool_end /* must be below end of pool */ \
255
+ )
247
256
248
257
#ifndef TRACE_MARK
249
258
#if DEBUG_PRINT
@@ -257,18 +266,20 @@ STATIC inline mp_state_mem_area_t *gc_get_ptr_area(const void *ptr) {
257
266
// children: mark the unmarked child blocks and put those newly marked
258
267
// blocks on the stack. When all children have been checked, pop off the
259
268
// topmost block on the stack and repeat with that one.
260
- STATIC void gc_mark_subtree (mp_gc_stack_item_t item ) {
261
- // Start with the item passed in the argument.
269
+ #if MICROPY_GC_MULTIHEAP
270
+ STATIC void gc_mark_subtree (mp_state_mem_area_t * area , size_t block )
271
+ #else
272
+ STATIC void gc_mark_subtree (size_t block )
273
+ #endif
274
+ {
275
+ // Start with the block passed in the argument.
262
276
size_t sp = 0 ;
263
277
for (;;) {
264
278
MICROPY_GC_HOOK_LOOP
265
279
266
- #if MICROPY_GC_MULTIHEAP
267
- mp_state_mem_area_t * area = item .area ;
268
- #else
269
- mp_state_mem_area_t * area = & MP_STATE_MEM (area );
280
+ #if !MICROPY_GC_MULTIHEAP
281
+ mp_state_mem_area_t * area = & MP_STATE_MEM (area );
270
282
#endif
271
- size_t block = item .block ;
272
283
273
284
// work out number of consecutive blocks in the chain starting with this one
274
285
size_t n_blocks = 0 ;
@@ -283,11 +294,18 @@ STATIC void gc_mark_subtree(mp_gc_stack_item_t item) {
283
294
void * ptr = * ptrs ;
284
295
// If this is a heap pointer that hasn't been marked, mark it and push
285
296
// it's children to the stack.
297
+ #if MICROPY_GC_MULTIHEAP
286
298
mp_state_mem_area_t * ptr_area = gc_get_ptr_area (ptr );
287
299
if (!ptr_area ) {
288
300
// Not a heap-allocated pointer (might even be random data).
289
301
continue ;
290
302
}
303
+ #else
304
+ if (!VERIFY_PTR (ptr )) {
305
+ continue ;
306
+ }
307
+ mp_state_mem_area_t * ptr_area = area ;
308
+ #endif
291
309
size_t ptr_block = BLOCK_FROM_PTR (ptr_area , ptr );
292
310
if (ATB_GET_KIND (ptr_area , ptr_block ) != AT_HEAD ) {
293
311
// This block is already marked.
@@ -297,24 +315,27 @@ STATIC void gc_mark_subtree(mp_gc_stack_item_t item) {
297
315
TRACE_MARK (ptr_block , ptr );
298
316
ATB_HEAD_TO_MARK (ptr_area , ptr_block );
299
317
if (sp < MICROPY_ALLOC_GC_STACK_SIZE ) {
318
+ MP_STATE_MEM (gc_block_stack )[sp ] = ptr_block ;
300
319
#if MICROPY_GC_MULTIHEAP
301
- mp_gc_stack_item_t ptr_item = {ptr_area , ptr_block };
302
- #else
303
- mp_gc_stack_item_t ptr_item = {ptr_block };
320
+ MP_STATE_MEM (gc_area_stack )[sp ] = ptr_area ;
304
321
#endif
305
- MP_STATE_MEM ( gc_stack )[ sp ++ ] = ptr_item ;
322
+ sp += 1 ;
306
323
} else {
307
324
MP_STATE_MEM (gc_stack_overflow ) = 1 ;
308
325
}
309
326
}
310
327
311
- // Are there any items on the stack?
328
+ // Are there any blocks on the stack?
312
329
if (sp == 0 ) {
313
330
break ; // No, stack is empty, we're done.
314
331
}
315
332
316
- // pop the next item off the stack
317
- item = MP_STATE_MEM (gc_stack )[-- sp ];
333
+ // pop the next block off the stack
334
+ sp -= 1 ;
335
+ block = MP_STATE_MEM (gc_block_stack )[sp ];
336
+ #if MICROPY_GC_MULTIHEAP
337
+ area = MP_STATE_MEM (gc_area_stack )[sp ];
338
+ #endif
318
339
}
319
340
}
320
341
@@ -329,13 +350,10 @@ STATIC void gc_deal_with_stack_overflow(void) {
329
350
// trace (again) if mark bit set
330
351
if (ATB_GET_KIND (area , block ) == AT_MARK ) {
331
352
#if MICROPY_GC_MULTIHEAP
332
- mp_gc_stack_item_t item = { area , block } ;
353
+ gc_mark_subtree ( area , block ) ;
333
354
#else
334
- mp_gc_stack_item_t item = { block } ;
355
+ gc_mark_subtree ( block ) ;
335
356
#endif
336
- // *MP_STATE_MEM(gc_sp)++ = item;
337
- // gc_drain_stack();
338
- gc_mark_subtree (item );
339
357
}
340
358
}
341
359
}
@@ -435,23 +453,32 @@ static void *gc_get_ptr(void **ptrs, int i) {
435
453
}
436
454
437
455
void gc_collect_root (void * * ptrs , size_t len ) {
456
+ #if !MICROPY_GC_MULTIHEAP
457
+ mp_state_mem_area_t * area = & MP_STATE_MEM (area );
458
+ #endif
438
459
for (size_t i = 0 ; i < len ; i ++ ) {
439
460
MICROPY_GC_HOOK_LOOP
440
461
// void *ptr = ptrs[i];
441
462
void * ptr = gc_get_ptr (ptrs , i );
463
+ #if MICROPY_GC_MULTIHEAP
442
464
mp_state_mem_area_t * area = gc_get_ptr_area (ptr );
443
- if (area ) {
444
- size_t block = BLOCK_FROM_PTR (area , ptr );
445
- if (ATB_GET_KIND (area , block ) == AT_HEAD ) {
446
- // An unmarked head: mark it, and mark all its children
447
- ATB_HEAD_TO_MARK (area , block );
448
- #if MICROPY_GC_MULTIHEAP
449
- mp_gc_stack_item_t item = {area , block };
450
- #else
451
- mp_gc_stack_item_t item = {block };
452
- #endif
453
- gc_mark_subtree (item );
454
- }
465
+ if (!area ) {
466
+ continue ;
467
+ }
468
+ #else
469
+ if (!VERIFY_PTR (ptr )) {
470
+ continue ;
471
+ }
472
+ #endif
473
+ size_t block = BLOCK_FROM_PTR (area , ptr );
474
+ if (ATB_GET_KIND (area , block ) == AT_HEAD ) {
475
+ // An unmarked head: mark it, and mark all its children
476
+ ATB_HEAD_TO_MARK (area , block );
477
+ #if MICROPY_GC_MULTIHEAP
478
+ gc_mark_subtree (area , block );
479
+ #else
480
+ gc_mark_subtree (block );
481
+ #endif
455
482
}
456
483
}
457
484
}
@@ -717,8 +744,15 @@ void gc_free(void *ptr) {
717
744
}
718
745
719
746
// get the GC block number corresponding to this pointer
720
- mp_state_mem_area_t * area = gc_get_ptr_area (ptr );
747
+ mp_state_mem_area_t * area ;
748
+ #if MICROPY_GC_MULTIHEAP
749
+ area = gc_get_ptr_area (ptr );
721
750
assert (area );
751
+ #else
752
+ assert (VERIFY_PTR (ptr ));
753
+ area = & MP_STATE_MEM (area );
754
+ #endif
755
+
722
756
size_t block = BLOCK_FROM_PTR (area , ptr );
723
757
assert (ATB_GET_KIND (area , block ) == AT_HEAD );
724
758
@@ -761,7 +795,18 @@ void gc_free(void *ptr) {
761
795
762
796
size_t gc_nbytes (const void * ptr ) {
763
797
GC_ENTER ();
764
- mp_state_mem_area_t * area = gc_get_ptr_area (ptr );
798
+
799
+ mp_state_mem_area_t * area ;
800
+ #if MICROPY_GC_MULTIHEAP
801
+ area = gc_get_ptr_area (ptr );
802
+ #else
803
+ if (VERIFY_PTR (ptr )) {
804
+ area = & MP_STATE_MEM (area );
805
+ } else {
806
+ area = NULL ;
807
+ }
808
+ #endif
809
+
765
810
if (area ) {
766
811
size_t block = BLOCK_FROM_PTR (area , ptr );
767
812
if (ATB_GET_KIND (area , block ) == AT_HEAD ) {
@@ -830,8 +875,14 @@ void *gc_realloc(void *ptr_in, size_t n_bytes, bool allow_move) {
830
875
GC_ENTER ();
831
876
832
877
// get the GC block number corresponding to this pointer
833
- mp_state_mem_area_t * area = gc_get_ptr_area (ptr );
878
+ mp_state_mem_area_t * area ;
879
+ #if MICROPY_GC_MULTIHEAP
880
+ area = gc_get_ptr_area (ptr );
834
881
assert (area );
882
+ #else
883
+ assert (VERIFY_PTR (ptr ));
884
+ area = & MP_STATE_MEM (area );
885
+ #endif
835
886
size_t block = BLOCK_FROM_PTR (area , ptr );
836
887
assert (ATB_GET_KIND (area , block ) == AT_HEAD );
837
888
0 commit comments