From f3dba3eb6bf44685cb2290d48204e81a84fc09a6 Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Wed, 3 Dec 2014 06:59:08 -0700 Subject: [PATCH] fix over-eager shortcut in the implementaiton of continuation jumps Don't jump past a prompt when jumping to a continuation that is a prefix of the current one. Reported by Max New --- .../racket-test/tests/racket/prompt-tests.rktl | 13 +++++++++++++ racket/src/racket/src/eval.c | 15 +++++++++++++-- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/pkgs/racket-pkgs/racket-test/tests/racket/prompt-tests.rktl b/pkgs/racket-pkgs/racket-test/tests/racket/prompt-tests.rktl index f90d533eed..888706338e 100644 --- a/pkgs/racket-pkgs/racket-test/tests/racket/prompt-tests.rktl +++ b/pkgs/racket-pkgs/racket-test/tests/racket/prompt-tests.rktl @@ -322,6 +322,19 @@ (test-breaks-ok) +;; Make sure a jump to an enclosing continuation doesn't +;; skip over a prompt: +(test 25 values (+ 5 + (call-with-continuation-prompt + (lambda () + (+ 1 + (call/cc + (lambda (k) + (+ 17 + (call-with-continuation-prompt + (lambda () + (k 1))))))))))) + ;; ---------------------------------------- ;; Overlapping continuations diff --git a/racket/src/racket/src/eval.c b/racket/src/racket/src/eval.c index de0b3bc891..f3d5786c66 100644 --- a/racket/src/racket/src/eval.c +++ b/racket/src/racket/src/eval.c @@ -1478,6 +1478,10 @@ static Scheme_Prompt *lookup_cont_prompt(Scheme_Cont *c, Scheme_Prompt *prompt; Scheme_Object *pt; + if (!c->runstack_copied) + /* This continuation is the same as another... */ + c = c->buf_ptr->buf.cont; + pt = c->prompt_tag; if (SCHEME_NP_CHAPERONEP(pt)) pt = SCHEME_CHAPERONE_VAL(pt); @@ -1615,10 +1619,17 @@ Scheme_Object *scheme_jump_to_continuation(Scheme_Object *obj, int num_rands, Sc c = (Scheme_Cont *)obj; + /* Shortcut: if the target continuation is an extension of the current + continuation, and if no prompt is in the way, then escape directly. */ if (can_ec && c->escape_cont - && scheme_escape_continuation_ok(c->escape_cont)) - scheme_escape_to_continuation(c->escape_cont, num_rands, rands, (Scheme_Object *)c); + && scheme_escape_continuation_ok(c->escape_cont)) { + prompt = lookup_cont_prompt(c, &prompt_mc, &prompt_pos, LOOKUP_NO_PROMPT); + if (!prompt || (prompt->id + && (prompt->id == c->prompt_id) + && !prompt_mc)) + scheme_escape_to_continuation(c->escape_cont, num_rands, rands, (Scheme_Object *)c); + } if (num_rands != 1) { GC_CAN_IGNORE Scheme_Object **vals;