diff --git a/src/gc.c b/src/gc.c index 4937c65ddf84e..6ff2b3e6a8851 100644 --- a/src/gc.c +++ b/src/gc.c @@ -1238,30 +1238,51 @@ NOINLINE static int gc_mark_module(jl_ptls_t ptls, jl_module_t *m, int d) return refyoung; } +// Handle the case where the stack is only partially copied. +STATIC_INLINE uintptr_t gc_get_stack_addr(void *_addr, uintptr_t offset, + uintptr_t lb, uintptr_t ub) +{ + uintptr_t addr = (uintptr_t)_addr; + if (addr >= lb && addr < ub) + return addr + offset; + return addr; +} + +STATIC_INLINE uintptr_t gc_read_stack(void *_addr, uintptr_t offset, + uintptr_t lb, uintptr_t ub) +{ + uintptr_t real_addr = gc_get_stack_addr(_addr, offset, lb, ub); + return *(uintptr_t*)real_addr; +} + static void gc_mark_stack(jl_ptls_t ptls, jl_value_t *ta, jl_gcframe_t *s, - intptr_t offset, int d) + uintptr_t offset, uintptr_t lb, uintptr_t ub, int d) { while (s != NULL) { - s = (jl_gcframe_t*)((char*)s + offset); - jl_value_t ***rts = (jl_value_t***)(((void**)s)+2); - size_t nr = s->nroots>>1; - if (s->nroots & 1) { - for(size_t i=0; i < nr; i++) { - jl_value_t **ptr = (jl_value_t**)((char*)rts[i] + offset); - if (*ptr != NULL) { - gc_push_root(ptls, *ptr, d); + jl_value_t ***rts = (jl_value_t***)(((void**)s) + 2); + size_t nroots = gc_read_stack(&s->nroots, offset, lb, ub); + size_t nr = nroots >> 1; + if (nroots & 1) { + for (size_t i = 0; i < nr; i++) { + void **slot = (void**)gc_read_stack(&rts[i], offset, lb, ub); + void *obj = (void*)gc_read_stack(slot, offset, lb, ub); + if (obj != NULL) { + gc_push_root(ptls, obj, d); } } } else { - for(size_t i=0; i < nr; i++) { - if (rts[i] != NULL) { - verify_parent2("task", ta, &rts[i], "stack(%d)", (int)i); - gc_push_root(ptls, rts[i], d); + for (size_t i=0; i < nr; i++) { + void *obj = (void*)gc_read_stack(&rts[i], offset, lb, ub); + if (obj) { + verify_parent2("task", ta, + gc_get_stack_addr(&rts[i], offset, lb, ub), + "stack(%d)", (int)i); + gc_push_root(ptls, obj, d); } } } - s = s->prev; + s = (jl_gcframe_t*)gc_read_stack(&s->prev, offset, lb, ub); } } @@ -1284,16 +1305,19 @@ static void gc_mark_task_stack(jl_ptls_t ptls, jl_task_t *ta, int d) #endif } if (ta == ptls2->current_task) { - gc_mark_stack(ptls, (jl_value_t*)ta, ptls2->pgcstack, 0, d); + gc_mark_stack(ptls, (jl_value_t*)ta, ptls2->pgcstack, + 0, 0, (uintptr_t)-1, d); } else if (stkbuf) { - intptr_t offset; + uintptr_t offset = 0; + uintptr_t lb = 0; + uintptr_t ub = (uintptr_t)-1; #ifdef COPY_STACKS - offset = (char *)ta->stkbuf - ((char *)ptls2->stackbase - ta->ssize); -#else - offset = 0; + ub = (uintptr_t)ptls2->stackbase; + lb = ub - ta->ssize; + offset = (uintptr_t)ta->stkbuf - lb; #endif - gc_mark_stack(ptls, (jl_value_t*)ta, ta->gcstack, offset, d); + gc_mark_stack(ptls, (jl_value_t*)ta, ta->gcstack, offset, lb, ub, d); } } diff --git a/src/task.c b/src/task.c index 22cbef056857d..da456112945a8 100644 --- a/src/task.c +++ b/src/task.c @@ -147,7 +147,8 @@ static void NOINLINE save_stack(jl_ptls_t ptls, jl_task_t *t) if (t->state == done_sym || t->state == failed_sym) return; char *frame_addr = (char*)jl_get_frame_addr(); - size_t nb = (char*)ptls->stackbase - frame_addr; + char *stackbase = (char*)ptls->stackbase; + size_t nb = stackbase > frame_addr ? stackbase - frame_addr : 0; char *buf; if (t->stkbuf == NULL || t->bufsz < nb) { buf = (char*)jl_gc_alloc_buf(ptls, nb);