handle NULL on hl_gc_mark_grow
@@ -607,6 +607,38 @@ HL_PRIM void **hl_gc_mark_grow( void **stack ) {
void **nstack = (void**)malloc(sizeof(void**) * nsize);
void **base_stack = mark_stack_end - mark_stack_size;
int avail = (int)(stack - base_stack);
+ if( nstack == NULL ) {
+ // try to recover / eliminate fully scanned elements
+ void **st = base_stack + 2;
+ void **out = st;
+ while( st < stack ) {
+ void **block = (void**)*st++;
+ unsigned char *page_bid = *st++;
+ gc_pheader *page = (gc_pheader*)((int_val)page_bid & ~(GC_PAGE_SIZE - 1));
+ int bid = ((int)(int_val)page_bid) & (GC_PAGE_SIZE - 1);
+ int size = page->sizes ? page->sizes[bid] * page->block_size : page->block_size;
+ int nwords = size / HL_WSIZE;
+ while( nwords-- ) {
+ void *p = *block++;
+ page = GC_GET_PAGE(p);
+ if( !page || ((((unsigned char*)p - (unsigned char*)page))%page->block_size) != 0 ) continue;
+ # ifdef HL_64
+ if( !INPAGE(p,page) ) continue;
+ # endif
+ bid = (int)((unsigned char*)p - (unsigned char*)page) / page->block_size;
+ if( page->sizes && page->sizes[bid] == 0 ) continue;
+ if( (page->bmp[bid>>3] & (1<<(bid&7))) == 0 ) {
+ // has ptr, let's keep it
+ *out++ = block;
+ *out++ = page_bid;
+ break;
+ }
+ }
+ }
+ if( out == mark_stack_end )
+ hl_fatal("Out of memory");
+ return out;
+ }
memcpy(nstack, base_stack, avail * sizeof(void*));
free(base_stack);
mark_stack_size = nsize;
