Skip to content

Commit

Permalink
Support partially copied stack
Browse files Browse the repository at this point in the history
This is less problematic than copying more stack.
  • Loading branch information
yuyichao committed Nov 28, 2016
1 parent 9320866 commit e701cbe
Show file tree
Hide file tree
Showing 2 changed files with 46 additions and 21 deletions.
64 changes: 44 additions & 20 deletions src/gc.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand All @@ -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);
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/task.c
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit e701cbe

Please sign in to comment.