@@ -1027,7 +1027,10 @@ enum {
10271027#define PUSH_CONT (vm , next_pc ) PUSH_CONT_REC(vm, next_pc, NORMAL_FRAME)
10281028#define PUSH_BOUNDARY_CONT (vm ) \
10291029 PUSH_CONT_REC(vm, BOUNDARY_FRAME_MARK, BOUNDARY_FRAME)
1030- #define PUSH_PROMPT_CONT (vm , tag ) PUSH_CONT_REC(vm, tag, PROMPT_FRAME)
1030+ #define PUSH_PROMPT_CONT (vm , tag ) do { \
1031+ PUSH_CONT_REC(vm, tag, PROMPT_FRAME); \
1032+ FP(vm) = SP(vm); \
1033+ } while (0)
10311034
10321035static SgWord apply_callN [2 ] = {
10331036 MERGE_INSN_VALUE2 (APPLY , 2 , 1 ),
@@ -1581,6 +1584,11 @@ static void install_prompt(SgVM *vm, SgPrompt *prompt);
15811584static void remove_prompt (SgVM * vm , SgPrompt * prompt );
15821585static SgObject abort_body (SgPromptNode * node , SgObject winders , SgObject args );
15831586
1587+ static SgObject throw_delimited_continuation_body (SgObject ,
1588+ SgContinuation * ,
1589+ SgObject ,
1590+ SgPrompt * );
1591+
15841592static SgObject throw_continuation_body (SgObject handlers ,
15851593 SgContinuation * c ,
15861594 SgObject args ,
@@ -1820,7 +1828,7 @@ static SgObject throw_cont_compute_handlers(SgContinuation *c,
18201828static SgObject throw_continuation (SgObject * argv , int argc , void * data )
18211829{
18221830 SgContinuation * c = (SgContinuation * )SG_CAR (data );
1823- SgObject handlers_to_call ;
1831+ SgObject handlers ;
18241832 SgVM * vm = Sg_VM ();
18251833 SgPrompt * prompt = (SgPrompt * )SG_CDR (data );
18261834
@@ -1837,9 +1845,20 @@ static SgObject throw_continuation(SgObject *argv, int argc, void *data)
18371845 }
18381846 save_cont (vm );
18391847 }
1840- handlers_to_call = throw_cont_compute_handlers (c , prompt , vm );
1841-
1842- return throw_continuation_body (handlers_to_call , c , argv [0 ], prompt );
1848+ if (c -> type == SG_DELIMIETED_CONTINUATION ) {
1849+ SgContinuation abort_c ;
1850+ SgPromptNode * node = search_prompt_node_by_tag (vm , prompt -> tag );
1851+ abort_c .winders = node -> prompt -> winders ;
1852+ abort_c .cstack = node -> prompt -> cstack ; /* Non-null to enable post-thunks */
1853+ abort_c .cont = NULL ;
1854+ abort_c .prev = NULL ;
1855+ abort_c .ehandler = SG_FALSE ;
1856+ handlers = throw_cont_compute_handlers (& abort_c , node -> prompt , vm );
1857+ return throw_delimited_continuation_body (handlers , c , argv [0 ], prompt );
1858+ } else {
1859+ handlers = throw_cont_compute_handlers (c , prompt , vm );
1860+ return throw_continuation_body (handlers , c , argv [0 ], prompt );
1861+ }
18431862}
18441863
18451864static SgObject sym_continuation = SG_FALSE ;
@@ -1867,6 +1886,7 @@ SgObject Sg_VMCallCC(SgObject proc)
18671886 cont -> cstack = vm -> cstack ;
18681887 cont -> prev = NULL ;
18691888 cont -> ehandler = SG_FALSE ;
1889+ cont -> type = SG_FULL_CONTINUATION ;
18701890
18711891
18721892 contproc = make_cont_subr (cont , NULL );
@@ -1913,6 +1933,7 @@ SgObject Sg_VMCallComp(SgObject proc, SgObject tag)
19131933 cont -> ehandler = SG_FALSE ;
19141934 cont -> cstack = NULL ; /* so that this continuation can be
19151935 run on any cstack state. */
1936+ cont -> type = SG_COMPOSABLE_CONTINUATION ;
19161937 contproc = make_cont_subr (cont , node -> prompt );
19171938
19181939 return Sg_VMApply1 (proc , contproc );
@@ -1934,41 +1955,39 @@ SgObject Sg_VMCallComp(SgObject proc, SgObject tag)
19341955static SgObject throw_delimited_continuation_cc (SgObject , void * * );
19351956
19361957static SgObject throw_delimited_continuation_body (SgObject handlers ,
1937- SgContinuation * c ,
1938- SgPrompt * capture_prompt ,
1939- SgObject args ,
1940- SgObject tag )
1958+ SgContinuation * c ,
1959+ SgObject args ,
1960+ SgPrompt * prompt )
19411961{
19421962 SgVM * vm = Sg_VM ();
19431963
19441964 /* Process abort handlers (post-thunks for unwinding) */
19451965 if (SG_PAIRP (handlers )) {
19461966 SgObject handler , chain ;
1947- void * data [5 ];
1967+ void * data [4 ];
19481968 handler = SG_CAAR (handlers );
19491969 chain = SG_CDAR (handlers );
19501970 data [0 ] = (void * )SG_CDR (handlers );
19511971 data [1 ] = (void * )c ;
1952- data [2 ] = (void * )capture_prompt ;
1953- data [3 ] = (void * )args ;
1954- data [4 ] = (void * )tag ;
1955- Sg_VMPushCC (throw_delimited_continuation_cc , data , 5 );
1956-
1972+ data [2 ] = (void * )args ;
1973+ data [3 ] = (void * )prompt ;
1974+ Sg_VMPushCC (throw_delimited_continuation_cc , data , 4 );
19571975 /* For abort/post-thunks, directly SET winders to the chain (not merge)
19581976 This is like abort_body which also sets vm->dynamicWinders = chain */
19591977 vm -> dynamicWinders = chain ;
19601978 return Sg_VMApply0 (handler );
19611979 } else {
19621980 /* All abort handlers processed. Now we need to:
19631981 1. Set up the new prompt
1964- 2. Compute wind-in handlers (pre-thunks) to restore the continuation's dynamic extent
1982+ 2. Compute wind-in handlers (pre-thunks) to restore the continuation's
1983+ dynamic extent
19651984 3. Run those handlers, then apply the continuation */
19661985
19671986 SgPrompt * new_prompt ;
1968- SgPromptNode * node = search_prompt_node_by_tag (vm , tag );
1987+ SgPromptNode * node = search_prompt_node_by_tag (vm , prompt -> tag );
19691988
19701989 if (!node ) {
1971- Sg_Error (UC ("Stale prompt in delimited continuation: %S" ), tag );
1990+ Sg_Error (UC ("Stale prompt in delimited continuation: %S" ), prompt -> tag );
19721991 }
19731992
19741993 /* Pop continuation frames up to and including the prompt frame */
@@ -1980,95 +1999,35 @@ static SgObject throw_delimited_continuation_body(SgObject handlers,
19801999 cont_frame = cont_frame -> prev ;
19812000 }
19822001
1983- /* Remove the original prompt and set continuation to just before the prompt */
2002+ /* Remove the original prompt and set continuation to just before
2003+ the prompt */
19842004 remove_prompt (vm , node -> prompt );
19852005 vm -> cont = node -> frame -> prev ;
19862006
19872007 /* Create a new prompt for the continuation */
1988- new_prompt = make_prompt (tag , SG_FALSE , vm );
2008+ new_prompt = make_prompt (prompt -> tag , SG_FALSE , vm );
19892009
19902010 CHECK_STACK (CONT_FRAME_SIZE , vm );
19912011 PUSH_PROMPT_CONT (vm , new_prompt );
1992- FP (vm ) = SP (vm );
19932012 install_prompt (vm , new_prompt );
19942013
1995- /* Now compute and run wind-in handlers using the composable continuation path.
1996- We've already aborted to the prompt, so current vm->dynamicWinders is at
1997- the prompt's level. We need to wind into c's winders. */
1998- {
1999- SgObject wind_handlers = throw_cont_compute_handlers (c , capture_prompt , vm );
2000- /* Use the regular composable continuation body to process these handlers */
2001- return throw_continuation_body (wind_handlers , c , args , capture_prompt );
2002- }
2014+ /* Now compute and run wind-in handlers using the composable
2015+ continuation path. We've already aborted to the prompt, so
2016+ current vm->dynamicWinders is at the prompt's level. We need to
2017+ wind into c's winders. */
2018+ SgObject wind_handlers = throw_cont_compute_handlers (c , prompt , vm );
2019+ /* Use the regular composable continuation body to process these handlers */
2020+ return throw_continuation_body (wind_handlers , c , args , prompt );
20032021 }
20042022}
20052023
20062024static SgObject throw_delimited_continuation_cc (SgObject result , void * * data )
20072025{
20082026 SgObject handlers = SG_OBJ (data [0 ]);
20092027 SgContinuation * c = (SgContinuation * )data [1 ];
2010- SgPrompt * capture_prompt = (SgPrompt * )data [2 ];
2011- SgObject args = SG_OBJ (data [3 ]);
2012- SgObject tag = SG_OBJ (data [4 ]);
2013- return throw_delimited_continuation_body (handlers , c , capture_prompt , args , tag );
2014- }
2015-
2016- static SgObject throw_delimited_continuation (SgObject * argv , int argc , void * data )
2017- {
2018- SgContinuation * c = SG_CONTINUATION (SG_CAAR (data ));
2019- SgPrompt * capture_prompt = (SgPrompt * )SG_CDAR (data );
2020- SgObject tag = SG_CDR (data );
2021- SgVM * vm = Sg_VM ();
2022- SgPromptNode * node = search_prompt_node_by_tag (vm , tag );
2023- SgObject h , args ;
2024-
2025- if (!node ) {
2026- Sg_Error (UC ("Continuation application: no corresponding prompt for tag ~S" ), tag );
2027- }
2028-
2029- /* argv[0] is already a list of arguments (folded by optional arg processing) */
2030- args = argv [0 ];
2031-
2032- /* Check for cross-cstack jumps */
2033- if (node -> prompt -> cstack != vm -> cstack ) {
2034- SgCStack * cs ;
2035- for (cs = vm -> cstack ; cs ; cs = cs -> prev ) {
2036- if (node -> prompt -> cstack == cs ) break ;
2037- }
2038- if (cs != NULL ) {
2039- /* Need to longjmp */
2040- vm -> escapeReason = SG_VM_ESCAPE_CONT ;
2041- vm -> escapeData [0 ] = c ;
2042- vm -> escapeData [1 ] = Sg_Cons (Sg_Cons (args , (SgObject )capture_prompt ), tag );
2043- longjmp (vm -> cstack -> jbuf , 1 );
2044- }
2045- }
2046-
2047- /* call/delimited-cc (call/cc-like): ALWAYS abort to the prompt and reinstall.
2048- This is the key difference from composable continuations which just
2049- continue from where they are.
2050-
2051- Run post-thunks to unwind from current to prompt. */
2052- {
2053- SgContinuation abort_c ;
2054- abort_c .winders = node -> prompt -> winders ;
2055- abort_c .cstack = node -> prompt -> cstack ; /* Non-null to enable post-thunks */
2056- abort_c .cont = NULL ;
2057- abort_c .prev = NULL ;
2058- abort_c .ehandler = SG_FALSE ;
2059- h = throw_cont_compute_handlers (& abort_c , node -> prompt , vm );
2060- }
2061-
2062- return throw_delimited_continuation_body (h , c , capture_prompt , args , tag );
2063- }
2064-
2065- static SgObject make_delimited_cont_subr (SgContinuation * cont , SgPrompt * prompt , SgObject tag )
2066- {
2067- /* data = ((cont . prompt) . tag) */
2068- return Sg_MakeSubr (throw_delimited_continuation ,
2069- Sg_Cons (Sg_Cons ((SgObject )cont , (SgObject )prompt ), tag ),
2070- 0 , 1 ,
2071- sym_continuation );
2028+ SgObject args = SG_OBJ (data [2 ]);
2029+ SgPrompt * prompt = (SgPrompt * )data [3 ];
2030+ return throw_delimited_continuation_body (handlers , c , args , prompt );
20722031}
20732032
20742033/* call-with-current-continuation with prompt delimiting (Racket-like call/cc) */
@@ -2093,9 +2052,10 @@ SgObject Sg_VMCallDelimitedCC(SgObject proc, SgObject tag)
20932052 cont -> prev = NULL ;
20942053 cont -> ehandler = SG_FALSE ;
20952054 cont -> cstack = NULL ;
2055+ cont -> type = SG_DELIMIETED_CONTINUATION ;
20962056
20972057 /* Pass the capture-time prompt so we know where to stop when splicing */
2098- contproc = make_delimited_cont_subr (cont , node -> prompt , tag );
2058+ contproc = make_cont_subr (cont , node -> prompt );
20992059
21002060 return Sg_VMApply1 (proc , contproc );
21012061 err :
@@ -2157,7 +2117,6 @@ SgObject Sg_VMCallCP(SgObject proc, SgObject tag,
21572117
21582118 CHECK_STACK (CONT_FRAME_SIZE , vm );
21592119 PUSH_PROMPT_CONT (vm , prompt );
2160- FP (vm ) = SP (vm );
21612120 install_prompt (vm , prompt );
21622121
21632122 return Sg_VMApply (proc , args );
0 commit comments