fix lack of space-safety in delimited continuations (related to recently fixed crashing bug)
svn: r9544
This commit is contained in:
parent
95aca3e86a
commit
abf86a46a8
63
collects/tests/mzscheme/prompt-sfs.ss
Normal file
63
collects/tests/mzscheme/prompt-sfs.ss
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
#lang scheme
|
||||||
|
|
||||||
|
#|
|
||||||
|
|
||||||
|
This test is designed to to check whether meta-continuations are
|
||||||
|
correctly split when a continuation is delimited in the middle of
|
||||||
|
a meta-continuation other than the current one. In aprticular,
|
||||||
|
the `x' binding is part of the deeper meta-continuation when `ak'
|
||||||
|
is captured, but it is delimited inside the binding, so `x'
|
||||||
|
should not be reated in `ak'.
|
||||||
|
|
||||||
|
|#
|
||||||
|
|
||||||
|
(define (make-big-thing) (cons (make-string 100000) (make-will-executor)))
|
||||||
|
(define (show-big-thing say x) (say (string-length (car x))))
|
||||||
|
|
||||||
|
(collect-garbage)
|
||||||
|
(collect-garbage)
|
||||||
|
(define orig (current-memory-use))
|
||||||
|
|
||||||
|
(define single (make-will-executor))
|
||||||
|
|
||||||
|
(let loop ([n 10][accums null])
|
||||||
|
(if (zero? n)
|
||||||
|
(begin
|
||||||
|
(collect-garbage)
|
||||||
|
(collect-garbage)
|
||||||
|
(dump-memory-stats) ; look for just one <will-executor>
|
||||||
|
(printf "~s\n" (- (current-memory-use) orig))
|
||||||
|
accums)
|
||||||
|
(let* ([says null]
|
||||||
|
[say (lambda (s)
|
||||||
|
(set! says (cons s says)))]
|
||||||
|
[a (make-continuation-prompt-tag 'a)]
|
||||||
|
[b (make-continuation-prompt-tag 'b)])
|
||||||
|
(let ([ak
|
||||||
|
(let ([x (make-big-thing)])
|
||||||
|
(begin0
|
||||||
|
(call-with-continuation-prompt
|
||||||
|
(lambda ()
|
||||||
|
(with-continuation-mark 'y "y0"
|
||||||
|
(let ([bk (call-with-continuation-prompt
|
||||||
|
(lambda ()
|
||||||
|
(let ([f (call-with-composable-continuation
|
||||||
|
(lambda (k)
|
||||||
|
(lambda () k))
|
||||||
|
b)])
|
||||||
|
(say "bcall")
|
||||||
|
(begin0
|
||||||
|
(f)
|
||||||
|
(say "breturn"))))
|
||||||
|
b)])
|
||||||
|
(call-with-continuation-prompt
|
||||||
|
(lambda ()
|
||||||
|
((bk (lambda ()
|
||||||
|
(let ([f (call/cc (lambda (k) (lambda () (lambda () k))) a)])
|
||||||
|
(begin0
|
||||||
|
(f)
|
||||||
|
(say "areturn")))))))
|
||||||
|
b))))
|
||||||
|
a)
|
||||||
|
(show-big-thing say x)))])
|
||||||
|
(loop (sub1 n) (cons ak accums))))))
|
|
@ -924,7 +924,7 @@ typedef struct Scheme_Thread {
|
||||||
|
|
||||||
mz_jmp_buf *error_buf;
|
mz_jmp_buf *error_buf;
|
||||||
Scheme_Continuation_Jump_State cjs;
|
Scheme_Continuation_Jump_State cjs;
|
||||||
struct Scheme_Cont *decompose;
|
struct Scheme_Meta_Continuation *decompose_mc; /* set during a jump */
|
||||||
|
|
||||||
Scheme_Thread_Cell_Table *cell_values;
|
Scheme_Thread_Cell_Table *cell_values;
|
||||||
Scheme_Config *init_config;
|
Scheme_Config *init_config;
|
||||||
|
|
|
@ -7123,7 +7123,7 @@ Scheme_Object *scheme_jump_to_continuation(Scheme_Object *obj, int num_rands, Sc
|
||||||
}
|
}
|
||||||
p->meta_continuation = prompt_mc->next;
|
p->meta_continuation = prompt_mc->next;
|
||||||
p->stack_start = prompt_mc->overflow->stack_start;
|
p->stack_start = prompt_mc->overflow->stack_start;
|
||||||
p->decompose = prompt_mc->cont;
|
p->decompose_mc = prompt_mc;
|
||||||
scheme_longjmpup(&prompt_mc->overflow->jmp->cont);
|
scheme_longjmpup(&prompt_mc->overflow->jmp->cont);
|
||||||
} else if ((!prompt->boundary_overflow_id && !p->overflow)
|
} else if ((!prompt->boundary_overflow_id && !p->overflow)
|
||||||
|| (prompt->boundary_overflow_id
|
|| (prompt->boundary_overflow_id
|
||||||
|
|
|
@ -194,7 +194,10 @@ typedef struct Scheme_Dynamic_Wind_List {
|
||||||
} Scheme_Dynamic_Wind_List;
|
} Scheme_Dynamic_Wind_List;
|
||||||
|
|
||||||
static Scheme_Object *cached_beg_stx, *cached_dv_stx, *cached_ds_stx;
|
static Scheme_Object *cached_beg_stx, *cached_dv_stx, *cached_ds_stx;
|
||||||
int cached_stx_phase;
|
static int cached_stx_phase;
|
||||||
|
|
||||||
|
static Scheme_Cont *offstack_cont;
|
||||||
|
static Scheme_Overflow *offstack_overflow;
|
||||||
|
|
||||||
/*========================================================================*/
|
/*========================================================================*/
|
||||||
/* initialization */
|
/* initialization */
|
||||||
|
@ -222,6 +225,9 @@ scheme_init_fun (Scheme_Env *env)
|
||||||
REGISTER_SO(cached_ds_stx);
|
REGISTER_SO(cached_ds_stx);
|
||||||
REGISTER_SO(scheme_procedure_p_proc);
|
REGISTER_SO(scheme_procedure_p_proc);
|
||||||
|
|
||||||
|
REGISTER_SO(offstack_cont);
|
||||||
|
REGISTER_SO(offstack_overflow);
|
||||||
|
|
||||||
o = scheme_make_folding_prim(procedure_p, "procedure?", 1, 1, 1);
|
o = scheme_make_folding_prim(procedure_p, "procedure?", 1, 1, 1);
|
||||||
SCHEME_PRIM_PROC_FLAGS(o) |= SCHEME_PRIM_IS_UNARY_INLINED;
|
SCHEME_PRIM_PROC_FLAGS(o) |= SCHEME_PRIM_IS_UNARY_INLINED;
|
||||||
scheme_add_global_constant("procedure?", o, env);
|
scheme_add_global_constant("procedure?", o, env);
|
||||||
|
@ -4050,6 +4056,7 @@ static Scheme_Saved_Stack *copy_out_runstack(Scheme_Thread *p,
|
||||||
start = MALLOC_N(Scheme_Object*, size);
|
start = MALLOC_N(Scheme_Object*, size);
|
||||||
saved->runstack_start = start;
|
saved->runstack_start = start;
|
||||||
memcpy(saved->runstack_start, runstack, size * sizeof(Scheme_Object *));
|
memcpy(saved->runstack_start, runstack, size * sizeof(Scheme_Object *));
|
||||||
|
saved->runstack_offset = (runstack XFORM_OK_MINUS runstack_start);
|
||||||
|
|
||||||
if (!effective_prompt || (effective_prompt->runstack_boundary_start != runstack_start)) {
|
if (!effective_prompt || (effective_prompt->runstack_boundary_start != runstack_start)) {
|
||||||
|
|
||||||
|
@ -4349,6 +4356,87 @@ static void clear_cm_copy_caches(Scheme_Cont_Mark *cp, int cnt)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Scheme_Saved_Stack *clone_runstack_saved(Scheme_Saved_Stack *saved, Scheme_Object **boundary_start,
|
||||||
|
Scheme_Saved_Stack *last)
|
||||||
|
{
|
||||||
|
Scheme_Saved_Stack *naya, *first = last, *prev = NULL;
|
||||||
|
|
||||||
|
while (saved) {
|
||||||
|
naya = MALLOC_ONE_RT(Scheme_Saved_Stack);
|
||||||
|
memcpy(naya, saved, sizeof(Scheme_Saved_Stack));
|
||||||
|
if (prev)
|
||||||
|
prev->prev = naya;
|
||||||
|
else
|
||||||
|
first = naya;
|
||||||
|
prev = naya;
|
||||||
|
if (saved->runstack_start == boundary_start)
|
||||||
|
break;
|
||||||
|
saved = saved->prev;
|
||||||
|
}
|
||||||
|
if (prev)
|
||||||
|
prev->prev = last;
|
||||||
|
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Scheme_Saved_Stack *clone_runstack_copied(Scheme_Saved_Stack *copied,
|
||||||
|
Scheme_Object **copied_start,
|
||||||
|
Scheme_Saved_Stack *saved,
|
||||||
|
Scheme_Object **boundary_start,
|
||||||
|
long boundary_offset)
|
||||||
|
{
|
||||||
|
Scheme_Saved_Stack *naya, *first = NULL, *prev = NULL, *s;
|
||||||
|
|
||||||
|
if (copied_start == boundary_start) {
|
||||||
|
naya = copied;
|
||||||
|
} else {
|
||||||
|
for (naya = copied->prev, s = saved;
|
||||||
|
s->runstack_start != boundary_start;
|
||||||
|
naya = naya->prev, s = s->prev) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((naya->runstack_offset + naya->runstack_size == boundary_offset)
|
||||||
|
&& !naya->prev) {
|
||||||
|
/* no need to prune anything */
|
||||||
|
return copied;
|
||||||
|
}
|
||||||
|
|
||||||
|
s = NULL;
|
||||||
|
while (copied) {
|
||||||
|
naya = MALLOC_ONE_RT(Scheme_Saved_Stack);
|
||||||
|
memcpy(naya, copied, sizeof(Scheme_Saved_Stack));
|
||||||
|
naya->prev = NULL;
|
||||||
|
if (prev)
|
||||||
|
prev->prev = naya;
|
||||||
|
else
|
||||||
|
first = naya;
|
||||||
|
prev = naya;
|
||||||
|
if ((!s && copied_start == boundary_start)
|
||||||
|
|| (s && (s->runstack_start == boundary_start))) {
|
||||||
|
long size;
|
||||||
|
Scheme_Object **a;
|
||||||
|
size = boundary_offset - naya->runstack_offset;
|
||||||
|
if (size < 0)
|
||||||
|
scheme_signal_error("negative stack-copy size while pruning");
|
||||||
|
if (size > naya->runstack_size)
|
||||||
|
scheme_signal_error("bigger stack-copy size while pruning: %d vs. %d", size, naya->runstack_size);
|
||||||
|
a = MALLOC_N(Scheme_Object *, size);
|
||||||
|
memcpy(a, naya->runstack_start, size * sizeof(Scheme_Object *));
|
||||||
|
naya->runstack_start = a;
|
||||||
|
naya->runstack_size = size;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
copied = copied->prev;
|
||||||
|
if (!s)
|
||||||
|
s = saved;
|
||||||
|
else
|
||||||
|
s = s->prev;
|
||||||
|
}
|
||||||
|
|
||||||
|
return first;
|
||||||
|
}
|
||||||
|
|
||||||
static Scheme_Meta_Continuation *clone_meta_cont(Scheme_Meta_Continuation *mc,
|
static Scheme_Meta_Continuation *clone_meta_cont(Scheme_Meta_Continuation *mc,
|
||||||
Scheme_Object *limit_tag, int limit_depth,
|
Scheme_Object *limit_tag, int limit_depth,
|
||||||
Scheme_Meta_Continuation *prompt_cont,
|
Scheme_Meta_Continuation *prompt_cont,
|
||||||
|
@ -4378,6 +4466,8 @@ static Scheme_Meta_Continuation *clone_meta_cont(Scheme_Meta_Continuation *mc,
|
||||||
if (SAME_OBJ(mc, prompt_cont)) {
|
if (SAME_OBJ(mc, prompt_cont)) {
|
||||||
/* Need only part of this meta-continuation's marks. */
|
/* Need only part of this meta-continuation's marks. */
|
||||||
long delta;
|
long delta;
|
||||||
|
void *stack_boundary;
|
||||||
|
|
||||||
delta = prompt->mark_boundary - naya->cont_mark_offset;
|
delta = prompt->mark_boundary - naya->cont_mark_offset;
|
||||||
if (delta) {
|
if (delta) {
|
||||||
naya->cont_mark_total -= delta;
|
naya->cont_mark_total -= delta;
|
||||||
|
@ -4396,8 +4486,18 @@ static Scheme_Meta_Continuation *clone_meta_cont(Scheme_Meta_Continuation *mc,
|
||||||
naya->cont_mark_stack_copied = NULL;
|
naya->cont_mark_stack_copied = NULL;
|
||||||
}
|
}
|
||||||
naya->cont_mark_pos_bottom = prompt->boundary_mark_pos;
|
naya->cont_mark_pos_bottom = prompt->boundary_mark_pos;
|
||||||
{
|
|
||||||
|
if ((prompt->boundary_overflow_id && (prompt->boundary_overflow_id == naya->overflow->id))
|
||||||
|
|| (!prompt->boundary_overflow_id && !naya->overflow->prev)) {
|
||||||
|
stack_boundary = prompt->stack_boundary;
|
||||||
|
} else {
|
||||||
|
stack_boundary = naya->overflow->stack_start;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (naya->cont) {
|
||||||
Scheme_Cont *cnaya;
|
Scheme_Cont *cnaya;
|
||||||
|
Scheme_Saved_Stack *saved;
|
||||||
|
|
||||||
cnaya = MALLOC_ONE_TAGGED(Scheme_Cont);
|
cnaya = MALLOC_ONE_TAGGED(Scheme_Cont);
|
||||||
memcpy(cnaya, naya->cont, sizeof(Scheme_Cont));
|
memcpy(cnaya, naya->cont, sizeof(Scheme_Cont));
|
||||||
|
|
||||||
|
@ -4408,10 +4508,40 @@ static Scheme_Meta_Continuation *clone_meta_cont(Scheme_Meta_Continuation *mc,
|
||||||
cnaya->cont_mark_pos_bottom = naya->cont_mark_pos_bottom;
|
cnaya->cont_mark_pos_bottom = naya->cont_mark_pos_bottom;
|
||||||
cnaya->cont_mark_stack_copied = naya->cont_mark_stack_copied;
|
cnaya->cont_mark_stack_copied = naya->cont_mark_stack_copied;
|
||||||
|
|
||||||
cnaya->prompt_stack_start = prompt->stack_boundary;
|
cnaya->prompt_stack_start = stack_boundary;
|
||||||
|
|
||||||
|
/* Prune unneeded runstack data */
|
||||||
|
saved = clone_runstack_copied(cnaya->runstack_copied,
|
||||||
|
cnaya->runstack_start,
|
||||||
|
cnaya->runstack_saved,
|
||||||
|
prompt->runstack_boundary_start,
|
||||||
|
prompt->runstack_boundary_offset);
|
||||||
|
cnaya->runstack_copied = saved;
|
||||||
|
|
||||||
|
/* Prune unneeded buffers */
|
||||||
|
if (prompt->runstack_boundary_start == cnaya->runstack_start)
|
||||||
|
saved = NULL;
|
||||||
|
else
|
||||||
|
saved = clone_runstack_saved(cnaya->runstack_saved,
|
||||||
|
prompt->runstack_boundary_start,
|
||||||
|
NULL);
|
||||||
|
cnaya->runstack_saved = saved;
|
||||||
|
|
||||||
cnaya->need_meta_prompt = 1;
|
cnaya->need_meta_prompt = 1;
|
||||||
}
|
}
|
||||||
|
if (naya->overflow && !naya->overflow->eot) {
|
||||||
|
/* Prune unneeded C-stack data */
|
||||||
|
Scheme_Overflow *onaya;
|
||||||
|
Scheme_Overflow_Jmp *jmp;
|
||||||
|
jmp = scheme_prune_jmpup(naya->overflow->jmp, stack_boundary);
|
||||||
|
if (jmp) {
|
||||||
|
onaya = MALLOC_ONE_RT(Scheme_Overflow);
|
||||||
|
memcpy(onaya, naya->overflow, sizeof(Scheme_Overflow));
|
||||||
|
naya->overflow = onaya;
|
||||||
|
onaya->jmp = jmp;
|
||||||
|
onaya->stack_start = stack_boundary;
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!mc->cm_caches) {
|
if (!mc->cm_caches) {
|
||||||
mc->cm_shared = 1;
|
mc->cm_shared = 1;
|
||||||
|
@ -4549,29 +4679,6 @@ void prune_cont_marks(Scheme_Meta_Continuation *resume_mc, Scheme_Cont *cont, Sc
|
||||||
sync_meta_cont(resume_mc);
|
sync_meta_cont(resume_mc);
|
||||||
}
|
}
|
||||||
|
|
||||||
Scheme_Saved_Stack *clone_runstack_saved(Scheme_Saved_Stack *saved, Scheme_Object **boundary_start,
|
|
||||||
Scheme_Saved_Stack *last)
|
|
||||||
{
|
|
||||||
Scheme_Saved_Stack *naya, *first = last, *prev = NULL;
|
|
||||||
|
|
||||||
while (saved) {
|
|
||||||
naya = MALLOC_ONE_RT(Scheme_Saved_Stack);
|
|
||||||
memcpy(naya, saved, sizeof(Scheme_Saved_Stack));
|
|
||||||
if (prev)
|
|
||||||
prev->prev = naya;
|
|
||||||
else
|
|
||||||
first = naya;
|
|
||||||
prev = naya;
|
|
||||||
if (saved->runstack_start == boundary_start)
|
|
||||||
break;
|
|
||||||
saved = saved->prev;
|
|
||||||
}
|
|
||||||
if (prev)
|
|
||||||
prev->prev = last;
|
|
||||||
|
|
||||||
return first;
|
|
||||||
}
|
|
||||||
|
|
||||||
static MZ_MARK_STACK_TYPE exec_dyn_wind_pres(Scheme_Dynamic_Wind_List *dwl,
|
static MZ_MARK_STACK_TYPE exec_dyn_wind_pres(Scheme_Dynamic_Wind_List *dwl,
|
||||||
int dwl_len,
|
int dwl_len,
|
||||||
Scheme_Cont *cont,
|
Scheme_Cont *cont,
|
||||||
|
@ -4751,7 +4858,10 @@ static Scheme_Cont *grab_continuation(Scheme_Thread *p, int for_prompt, int comp
|
||||||
(for_prompt ? p->meta_prompt : prompt));
|
(for_prompt ? p->meta_prompt : prompt));
|
||||||
cont->runstack_copied = saved;
|
cont->runstack_copied = saved;
|
||||||
if (!for_prompt && prompt) {
|
if (!for_prompt && prompt) {
|
||||||
/* Prune cont->runstack_saved to drop unneeded saves. */
|
/* Prune cont->runstack_saved to drop unneeded saves.
|
||||||
|
(Note that this is different than runstack_copied;
|
||||||
|
runstack_saved keeps the shared runstack buffers,
|
||||||
|
not the content.) */
|
||||||
if (SAME_OBJ(prompt->runstack_boundary_start, MZ_RUNSTACK_START))
|
if (SAME_OBJ(prompt->runstack_boundary_start, MZ_RUNSTACK_START))
|
||||||
saved = NULL;
|
saved = NULL;
|
||||||
else
|
else
|
||||||
|
@ -5626,7 +5736,7 @@ Scheme_Object *scheme_finish_apply_for_prompt(Scheme_Prompt *prompt, Scheme_Obje
|
||||||
p->cjs.val = val;
|
p->cjs.val = val;
|
||||||
}
|
}
|
||||||
p->stack_start = resume->stack_start;
|
p->stack_start = resume->stack_start;
|
||||||
p->decompose = resume_mc->cont;
|
p->decompose_mc = resume_mc;
|
||||||
scheme_longjmpup(&resume->jmp->cont);
|
scheme_longjmpup(&resume->jmp->cont);
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
@ -5689,11 +5799,17 @@ static Scheme_Object *compose_continuation(Scheme_Cont *cont, int exec_chain,
|
||||||
overflow->jmp = jmp;
|
overflow->jmp = jmp;
|
||||||
|
|
||||||
saved->resume_to = overflow; /* used by eval to jump to current meta-continuation */
|
saved->resume_to = overflow; /* used by eval to jump to current meta-continuation */
|
||||||
cont->use_next_cont = saved;
|
offstack_cont = saved;
|
||||||
saved = NULL;
|
saved = NULL;
|
||||||
|
|
||||||
scheme_init_jmpup_buf(&overflow->jmp->cont);
|
scheme_init_jmpup_buf(&overflow->jmp->cont);
|
||||||
if (scheme_setjmpup(&overflow->jmp->cont, overflow->jmp, ADJUST_STACK_START(p->stack_start))) {
|
|
||||||
|
offstack_overflow = overflow;
|
||||||
|
overflow = NULL; /* so it's not saved in the continuation */
|
||||||
|
|
||||||
|
if (scheme_setjmpup(&offstack_overflow->jmp->cont,
|
||||||
|
offstack_overflow->jmp,
|
||||||
|
ADJUST_STACK_START(p->stack_start))) {
|
||||||
/* Returning. (Jumped here from finish_apply_for_prompt,
|
/* Returning. (Jumped here from finish_apply_for_prompt,
|
||||||
scheme_compose_continuation, scheme_eval, or start_child.)
|
scheme_compose_continuation, scheme_eval, or start_child.)
|
||||||
|
|
||||||
|
@ -5709,12 +5825,14 @@ static Scheme_Object *compose_continuation(Scheme_Cont *cont, int exec_chain,
|
||||||
scheme_finish_apply_for_prompt() for those possibilities.
|
scheme_finish_apply_for_prompt() for those possibilities.
|
||||||
*/
|
*/
|
||||||
Scheme_Object *v;
|
Scheme_Object *v;
|
||||||
Scheme_Meta_Continuation *mc;
|
Scheme_Meta_Continuation *mc, *dmc;
|
||||||
|
|
||||||
p = scheme_current_thread;
|
p = scheme_current_thread;
|
||||||
|
|
||||||
saved = p->decompose;
|
dmc = p->decompose_mc;
|
||||||
p->decompose = NULL;
|
p->decompose_mc = NULL;
|
||||||
|
saved = dmc->cont;
|
||||||
|
overflow = dmc->overflow;
|
||||||
|
|
||||||
if (!p->cjs.jumping_to_continuation) {
|
if (!p->cjs.jumping_to_continuation) {
|
||||||
/* Got a result: */
|
/* Got a result: */
|
||||||
|
@ -5765,16 +5883,21 @@ static Scheme_Object *compose_continuation(Scheme_Cont *cont, int exec_chain,
|
||||||
reset_cjs(&p->cjs);
|
reset_cjs(&p->cjs);
|
||||||
/* The current meta-continuation may have changed since capture: */
|
/* The current meta-continuation may have changed since capture: */
|
||||||
saved->meta_continuation = p->meta_continuation;
|
saved->meta_continuation = p->meta_continuation;
|
||||||
cont->use_next_cont = saved;
|
|
||||||
/* Fall though to continuation application below. */
|
/* Fall though to continuation application below. */
|
||||||
} else {
|
} else {
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
saved = offstack_cont;
|
||||||
|
overflow = offstack_overflow;
|
||||||
|
offstack_cont = NULL;
|
||||||
|
offstack_overflow = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
scheme_current_thread->suspend_break++;
|
scheme_current_thread->suspend_break++;
|
||||||
|
|
||||||
/* Here's where we jump to the target: */
|
/* Here's where we jump to the target: */
|
||||||
|
cont->use_next_cont = saved;
|
||||||
cont->resume_to = overflow;
|
cont->resume_to = overflow;
|
||||||
cont->empty_to_next_mc = (char)empty_to_next_mc;
|
cont->empty_to_next_mc = (char)empty_to_next_mc;
|
||||||
scheme_current_thread->stack_start = cont->prompt_stack_start;
|
scheme_current_thread->stack_start = cont->prompt_stack_start;
|
||||||
|
@ -6228,7 +6351,7 @@ Scheme_Object *scheme_compose_continuation(Scheme_Cont *cont, int num_rands, Sch
|
||||||
p->cjs.is_escape = 1;
|
p->cjs.is_escape = 1;
|
||||||
|
|
||||||
p->stack_start = mc->overflow->stack_start;
|
p->stack_start = mc->overflow->stack_start;
|
||||||
p->decompose = mc->cont;
|
p->decompose_mc = mc;
|
||||||
|
|
||||||
scheme_longjmpup(&mc->overflow->jmp->cont);
|
scheme_longjmpup(&mc->overflow->jmp->cont);
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
|
@ -929,8 +929,6 @@ static int cont_proc_MARK(void *p) {
|
||||||
gcMARK(c->prompt_id);
|
gcMARK(c->prompt_id);
|
||||||
gcMARK(c->prompt_buf);
|
gcMARK(c->prompt_buf);
|
||||||
|
|
||||||
/* These shouldn't actually persist across a GC, but
|
|
||||||
just in case... */
|
|
||||||
gcMARK(c->value);
|
gcMARK(c->value);
|
||||||
gcMARK(c->resume_to);
|
gcMARK(c->resume_to);
|
||||||
gcMARK(c->use_next_cont);
|
gcMARK(c->use_next_cont);
|
||||||
|
@ -969,8 +967,6 @@ static int cont_proc_FIXUP(void *p) {
|
||||||
gcFIXUP(c->prompt_id);
|
gcFIXUP(c->prompt_id);
|
||||||
gcFIXUP(c->prompt_buf);
|
gcFIXUP(c->prompt_buf);
|
||||||
|
|
||||||
/* These shouldn't actually persist across a GC, but
|
|
||||||
just in case... */
|
|
||||||
gcFIXUP(c->value);
|
gcFIXUP(c->value);
|
||||||
gcFIXUP(c->resume_to);
|
gcFIXUP(c->resume_to);
|
||||||
gcFIXUP(c->use_next_cont);
|
gcFIXUP(c->use_next_cont);
|
||||||
|
@ -1598,7 +1594,7 @@ static int thread_val_MARK(void *p) {
|
||||||
gcMARK(pr->t_set_prev);
|
gcMARK(pr->t_set_prev);
|
||||||
|
|
||||||
MARK_cjs(&pr->cjs);
|
MARK_cjs(&pr->cjs);
|
||||||
gcMARK(pr->decompose);
|
gcMARK(pr->decompose_mc);
|
||||||
|
|
||||||
gcMARK(pr->cell_values);
|
gcMARK(pr->cell_values);
|
||||||
gcMARK(pr->init_config);
|
gcMARK(pr->init_config);
|
||||||
|
@ -1699,7 +1695,7 @@ static int thread_val_FIXUP(void *p) {
|
||||||
gcFIXUP(pr->t_set_prev);
|
gcFIXUP(pr->t_set_prev);
|
||||||
|
|
||||||
FIXUP_cjs(&pr->cjs);
|
FIXUP_cjs(&pr->cjs);
|
||||||
gcFIXUP(pr->decompose);
|
gcFIXUP(pr->decompose_mc);
|
||||||
|
|
||||||
gcFIXUP(pr->cell_values);
|
gcFIXUP(pr->cell_values);
|
||||||
gcFIXUP(pr->init_config);
|
gcFIXUP(pr->init_config);
|
||||||
|
|
|
@ -361,8 +361,6 @@ cont_proc {
|
||||||
gcMARK(c->prompt_id);
|
gcMARK(c->prompt_id);
|
||||||
gcMARK(c->prompt_buf);
|
gcMARK(c->prompt_buf);
|
||||||
|
|
||||||
/* These shouldn't actually persist across a GC, but
|
|
||||||
just in case... */
|
|
||||||
gcMARK(c->value);
|
gcMARK(c->value);
|
||||||
gcMARK(c->resume_to);
|
gcMARK(c->resume_to);
|
||||||
gcMARK(c->use_next_cont);
|
gcMARK(c->use_next_cont);
|
||||||
|
@ -611,7 +609,7 @@ thread_val {
|
||||||
gcMARK(pr->t_set_prev);
|
gcMARK(pr->t_set_prev);
|
||||||
|
|
||||||
MARK_cjs(&pr->cjs);
|
MARK_cjs(&pr->cjs);
|
||||||
gcMARK(pr->decompose);
|
gcMARK(pr->decompose_mc);
|
||||||
|
|
||||||
gcMARK(pr->cell_values);
|
gcMARK(pr->cell_values);
|
||||||
gcMARK(pr->init_config);
|
gcMARK(pr->init_config);
|
||||||
|
|
|
@ -978,6 +978,8 @@ extern void *scheme_deepest_stack_start;
|
||||||
# define ADJUST_STACK_START(start) (start ? start : scheme_deepest_stack_start)
|
# define ADJUST_STACK_START(start) (start ? start : scheme_deepest_stack_start)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct Scheme_Overflow_Jmp *scheme_prune_jmpup(struct Scheme_Overflow_Jmp *jmp, void *stack_boundary);
|
||||||
|
|
||||||
void scheme_jmpup_free(Scheme_Jumpup_Buf *);
|
void scheme_jmpup_free(Scheme_Jumpup_Buf *);
|
||||||
void *scheme_enlarge_runstack(long size, void *(*k)());
|
void *scheme_enlarge_runstack(long size, void *(*k)());
|
||||||
int scheme_check_runstack(long size);
|
int scheme_check_runstack(long size);
|
||||||
|
|
|
@ -466,24 +466,26 @@ static void *align_var_stack(void **vs, void *s)
|
||||||
}
|
}
|
||||||
#define ALIGN_VAR_STACK(vs, s) s = align_var_stack(vs, s)
|
#define ALIGN_VAR_STACK(vs, s) s = align_var_stack(vs, s)
|
||||||
|
|
||||||
static void *shift_var_stack(void *s)
|
static void *shift_var_stack(void *s, long delta)
|
||||||
{
|
{
|
||||||
#ifdef STACK_GROWS_UP
|
#ifdef STACK_GROWS_UP
|
||||||
return s;
|
return s;
|
||||||
#else
|
#else
|
||||||
void **vs = (void **)s;
|
void **vs = (void **)(s + delta);
|
||||||
long cnt;
|
long cnt;
|
||||||
|
|
||||||
/* Set s past end of vs: */
|
/* Set s past end of vs: */
|
||||||
cnt = ((long *)vs)[1];
|
cnt = ((long *)vs)[1];
|
||||||
return (void *)(vs + cnt + 2);
|
return (void *)((void **)s + cnt + 2);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
#define PAST_VAR_STACK(s) s = shift_var_stack(s);
|
#define PAST_VAR_STACK(s) s = shift_var_stack(s, 0);
|
||||||
|
#define PAST_VAR_STACK_DELTA(s, d) s = shift_var_stack(s, d);
|
||||||
END_XFORM_SKIP;
|
END_XFORM_SKIP;
|
||||||
#else
|
#else
|
||||||
# define ALIGN_VAR_STACK(vs, s) /* empty */
|
# define ALIGN_VAR_STACK(vs, s) /* empty */
|
||||||
# define PAST_VAR_STACK(s) /* empty */
|
# define PAST_VAR_STACK(s) /* empty */
|
||||||
|
# define PAST_VAR_STACK_DELTA(s, d) /* empty */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
int scheme_setjmpup_relative(Scheme_Jumpup_Buf *b, void *base,
|
int scheme_setjmpup_relative(Scheme_Jumpup_Buf *b, void *base,
|
||||||
|
@ -550,6 +552,62 @@ int scheme_setjmpup_relative(Scheme_Jumpup_Buf *b, void *base,
|
||||||
return local;
|
return local;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct Scheme_Overflow_Jmp *scheme_prune_jmpup(struct Scheme_Overflow_Jmp *jmp, void *stack_boundary)
|
||||||
|
{
|
||||||
|
void *cur_end;
|
||||||
|
|
||||||
|
PAST_VAR_STACK_DELTA(stack_boundary, (void *)get_copy(jmp->cont.stack_copy) - (void *)jmp->cont.stack_from);
|
||||||
|
|
||||||
|
#ifdef STACK_GROWS_UP
|
||||||
|
cur_end = (void *)jmp->cont.stack_from;
|
||||||
|
#else
|
||||||
|
cur_end = (void *)((char *)jmp->cont.stack_from + jmp->cont.stack_size);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (stack_boundary != cur_end) {
|
||||||
|
long new_size, delta;
|
||||||
|
Scheme_Overflow_Jmp *naya;
|
||||||
|
void *copy, *base;
|
||||||
|
|
||||||
|
# ifdef STACK_GROWS_UP
|
||||||
|
delta = (char *)stack_boundary - (char *)jmp->cont.stack_from;
|
||||||
|
new_size = jmp->cont.stack_size - delta;
|
||||||
|
base = (char *)stack_boundary;
|
||||||
|
# else
|
||||||
|
delta = 0;
|
||||||
|
new_size = (long)stack_boundary - (long)jmp->cont.stack_from;
|
||||||
|
base = jmp->cont.stack_from;
|
||||||
|
# endif
|
||||||
|
|
||||||
|
if ((new_size < 0) || (new_size > jmp->cont.stack_size))
|
||||||
|
scheme_signal_error("bad C-stack pruigin size: %ld vs. %ld", new_size, jmp->cont.stack_size);
|
||||||
|
|
||||||
|
naya = MALLOC_ONE_RT(Scheme_Overflow_Jmp);
|
||||||
|
memcpy(naya, jmp, sizeof(Scheme_Overflow_Jmp));
|
||||||
|
scheme_init_jmpup_buf(&naya->cont);
|
||||||
|
|
||||||
|
#ifndef MZ_PRECISE_GC
|
||||||
|
copy = make_stack_copy_rec(new_size);
|
||||||
|
naya->cont.stack_copy = copy;
|
||||||
|
set_copy(naya->cont.stack_copy, MALLOC_STACK(new_size));
|
||||||
|
#else
|
||||||
|
copy = MALLOC_STACK(new_size);
|
||||||
|
set_copy(naya->cont.stack_copy, copy);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
memcpy(get_copy(copy),
|
||||||
|
get_copy(jmp->cont.stack_copy) XFORM_OK_PLUS delta,
|
||||||
|
new_size);
|
||||||
|
|
||||||
|
naya->cont.stack_size = naya->cont.stack_max_size = new_size;
|
||||||
|
naya->cont.stack_from = base;
|
||||||
|
|
||||||
|
return naya;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
void scheme_longjmpup(Scheme_Jumpup_Buf *b)
|
void scheme_longjmpup(Scheme_Jumpup_Buf *b)
|
||||||
{
|
{
|
||||||
long z;
|
long z;
|
||||||
|
|
|
@ -2790,7 +2790,7 @@ static void start_child(Scheme_Thread * volatile child,
|
||||||
p->meta_continuation = mc->next;
|
p->meta_continuation = mc->next;
|
||||||
if (!oflow->eot) {
|
if (!oflow->eot) {
|
||||||
p->stack_start = oflow->stack_start;
|
p->stack_start = oflow->stack_start;
|
||||||
p->decompose = mc->cont;
|
p->decompose_mc = mc;
|
||||||
scheme_longjmpup(&oflow->jmp->cont);
|
scheme_longjmpup(&oflow->jmp->cont);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user