From 40c892ff80521461583d598606298e44fd4e0e9f Mon Sep 17 00:00:00 2001 From: Matthew Flatt Date: Wed, 20 Jun 2012 07:33:01 +0800 Subject: [PATCH] futures: future-local handling of stack overflow Includes the addition of 'overflow and 'start-overflow-work events, whcih are effectively specializations of 'sync and 'start-work to expose overflow handling. Also, fix a bug related to a potential GC during mark-stack restore from a lightweight continuation. --- collects/scribblings/reference/futures.scrbl | 22 +- collects/tests/future/future.rkt | 31 ++ doc/release-notes/racket/HISTORY.txt | 5 +- src/racket/include/schthread.h | 2 +- src/racket/src/fun.c | 51 ++- src/racket/src/future.c | 357 +++++++++++++++---- src/racket/src/future.h | 20 +- src/racket/src/gen-jit-ts.rkt | 2 +- src/racket/src/jit_ts_def.c | 180 +++++----- src/racket/src/jit_ts_future_glue.c | 220 ++++++------ src/racket/src/jit_ts_protos.h | 52 +-- src/racket/src/jitcall.c | 43 ++- src/racket/src/mzmark_future.inc | 2 + src/racket/src/mzmarksrc.c | 1 + src/racket/src/schpriv.h | 2 + 15 files changed, 674 insertions(+), 316 deletions(-) diff --git a/collects/scribblings/reference/futures.scrbl b/collects/scribblings/reference/futures.scrbl index 8b7a6abcf7..35574cade0 100644 --- a/collects/scribblings/reference/futures.scrbl +++ b/collects/scribblings/reference/futures.scrbl @@ -188,7 +188,11 @@ a data value that is an instance of a @racket[future-event] @tech{prefab} structure: @racketblock[ -(define-struct future-event (future-id proc-id action time unsafe-op-name) +(define-struct future-event (future-id + proc-id + action + time + unsafe-op-name) #:prefab) ] @@ -222,6 +226,10 @@ The @racket[action] field is a symbol: started in a process other than 0 (e.g., the thunk requires too much local storage to start).} + @item{@racket['start-overflow-work]: like @racket['start-work], where + the future thunk's work was previously stopped due to an + internal stack overflow.} + @item{@racket['sync]: blocking (processes other than 0) or initiation of handing (process 0) for an ``unsafe'' operation in a future thunk's evaluation; the operation must run in process 0.} @@ -235,6 +243,10 @@ The @racket[action] field is a symbol: @racket['block], but for a @racket[touch] operation within a future thunk.} + @item{@racket['overflow] (never in process 0): like @racket['sync] or + @racket['block], but for the case that a process encountered an + internal stack overflow while evaluating a future thunk.} + @item{@racket['result] or @racket['abort]: waiting or handling for @racket['sync], @racket['block], or @racket['touch] ended with a value or an error, respectively.} @@ -255,15 +267,15 @@ The @racket[action] field is a symbol: ] -Assuming no @racket['missing] events, then @racket['start-work] or -@racket['start-0-work] is always paired with @racket['end-work], +Assuming no @racket['missing] events, then @racket['start-work], +@racket['start-0-work], @racket['start-overflow-work] is always paired with @racket['end-work]; @racket['sync], @racket['block], and @racket['touch] are always paired -with @racket['result], @racket['abort], or @racket['suspend], and +with @racket['result], @racket['abort], or @racket['suspend]; and @racket['touch-pause] is always paired with @racket['touch-resume]. In process 0, some event pairs can be nested within other event pairs: @racket['sync], @racket['block], or @racket['touch] with -@racket['result] or @racket['abort], and @racket['touch-pause] with +@racket['result] or @racket['abort]; and @racket['touch-pause] with @racket['touch-resume]. An @racket[block] in process 0 is generated when an unsafe operation diff --git a/collects/tests/future/future.rkt b/collects/tests/future/future.rkt index 5d27a8f303..251864cece 100644 --- a/collects/tests/future/future.rkt +++ b/collects/tests/future/future.rkt @@ -819,6 +819,37 @@ We should also test deep continuations. (check-equal? (unbox b2) #false) (neg-good) (check-equal? (unbox b2) #true)) + + ;; check handling of marks in stack-overflow handling: + (let () + (define (maybe-add1 n) + (if (number? n) + (add1 n) + n)) + (define (loop n) + (if (zero? n) + (continuation-mark-set->list (current-continuation-marks) 'x) + (with-continuation-mark + 'x + n + (maybe-add1 (loop (sub1 n)))))) + (define f (func (lambda () (loop 10000)))) + (check-equal? 10000 (length (touch f)))) + + ;; check arity error in overflow handling: + (let () + (define (loop n) + (if (zero? n) + (values 0 0) + (add1 (loop (sub1 n))))) + + (for ([i (in-range 1340 1320 -1)]) + (define f (func (lambda () (loop i)))) + (sleep 0.1) + (with-handlers ([exn:fail? (lambda (exn) + (unless (regexp-match #rx"context" (exn-message exn)) + (raise exn)))]) + (touch f)))) ) (run-tests future) diff --git a/doc/release-notes/racket/HISTORY.txt b/doc/release-notes/racket/HISTORY.txt index a5f00588d6..fcb7cd12d8 100644 --- a/doc/release-notes/racket/HISTORY.txt +++ b/doc/release-notes/racket/HISTORY.txt @@ -1,7 +1,10 @@ Version 5.3.0.11 racket/base: added impersonate-prompt-tag & chaperone-prompt-tag racket/control: added call/prompt, call/comp, abort/cc and -allow #:tag argument for % and f-control + allow #:tag argument for % and f-control +racket/future: handling of internal stack overflow without + necessarily blocking on process 0; added 'overflow and + 'start-overflow-work log events Version 5.3.0.10 racket/base: add progress-evt?, thread-cell-values?, prefab-key?, diff --git a/src/racket/include/schthread.h b/src/racket/include/schthread.h index 2a43b0c116..04488499fd 100644 --- a/src/racket/include/schthread.h +++ b/src/racket/include/schthread.h @@ -238,7 +238,7 @@ typedef struct Thread_Local_Variables { int scheme_did_gc_count_; struct Scheme_Future_State *scheme_future_state_; struct Scheme_Future_Thread_State *scheme_future_thread_state_; - void *jit_future_storage_[2]; + void *jit_future_storage_[4]; struct Scheme_Object **scheme_current_runstack_start_; struct Scheme_Object **scheme_current_runstack_; intptr_t scheme_current_cont_mark_stack_; diff --git a/src/racket/src/fun.c b/src/racket/src/fun.c index 3212a3194e..e67928bec1 100644 --- a/src/racket/src/fun.c +++ b/src/racket/src/fun.c @@ -7855,8 +7855,7 @@ Scheme_Object *scheme_apply_lightweight_continuation(Scheme_Lightweight_Continua intptr_t min_stacksize) XFORM_SKIP_PROC { - intptr_t len, cm_len, cm_pos_delta, cm_delta, i, cm; - Scheme_Cont_Mark *seg; + intptr_t len, cm_delta, i, cm; Scheme_Object **rs; len = lw->saved_lwc->runstack_start - lw->saved_lwc->runstack_end; @@ -7882,18 +7881,13 @@ Scheme_Object *scheme_apply_lightweight_continuation(Scheme_Lightweight_Continua scheme_current_lwc->cont_mark_stack_start = MZ_CONT_MARK_STACK; scheme_current_lwc->cont_mark_pos_start = MZ_CONT_MARK_POS + 2; - cm_len = lw->saved_lwc->cont_mark_stack_end - lw->saved_lwc->cont_mark_stack_start; - if (cm_len) { - /* install captured continuation marks, adjusting the pos - to match the new context: */ - seg = lw->cont_mark_stack_slice; - cm_pos_delta = MZ_CONT_MARK_POS + 2 - lw->saved_lwc->cont_mark_pos_start; - for (i = 0; i < cm_len; i++) { - MZ_CONT_MARK_POS = seg[i].pos + cm_pos_delta; - scheme_set_cont_mark(seg[i].key, seg[i].val); - } - MZ_CONT_MARK_POS = lw->saved_lwc->cont_mark_pos_end + cm_pos_delta; - } +#ifdef MZ_USE_FUTURES + jit_future_storage[3] = result; +#endif + lw = scheme_restore_lightweight_continuation_marks(lw); /* can trigger GC */ +#ifdef MZ_USE_FUTURES + result = (Scheme_Object *)jit_future_storage[3]; +#endif cm_delta = (intptr_t)MZ_CONT_MARK_STACK - (intptr_t)lw->saved_lwc->cont_mark_stack_end; @@ -7918,6 +7912,35 @@ Scheme_Object *scheme_apply_lightweight_continuation(Scheme_Lightweight_Continua return scheme_apply_lightweight_continuation_stack(lw->saved_lwc, lw->stack_slice, result); } +Scheme_Lightweight_Continuation *scheme_restore_lightweight_continuation_marks(Scheme_Lightweight_Continuation *lw) + XFORM_SKIP_PROC +/* Called by any thread, but this function can trigger a GC in the runtime thread */ +{ + intptr_t cm_len, i, cm_pos_delta; + Scheme_Cont_Mark *seg; + + cm_len = lw->saved_lwc->cont_mark_stack_end - lw->saved_lwc->cont_mark_stack_start; + if (cm_len) { + /* install captured continuation marks, adjusting the pos + to match the new context: */ + seg = lw->cont_mark_stack_slice; + cm_pos_delta = MZ_CONT_MARK_POS + 2 - lw->saved_lwc->cont_mark_pos_start; + for (i = 0; i < cm_len; i++) { + MZ_CONT_MARK_POS = seg[i].pos + cm_pos_delta; +#ifdef MZ_USE_FUTURES + jit_future_storage[2] = lw; +#endif + scheme_set_cont_mark(seg[i].key, seg[i].val); /* can trigger a GC */ +#ifdef MZ_USE_FUTURES + lw = (Scheme_Lightweight_Continuation *)jit_future_storage[2]; +#endif + } + MZ_CONT_MARK_POS = lw->saved_lwc->cont_mark_pos_end + cm_pos_delta; + } + + return lw; +} + int scheme_push_marks_from_lightweight_continuation(Scheme_Lightweight_Continuation *lw, Scheme_Cont_Frame_Data *d) { diff --git a/src/racket/src/future.c b/src/racket/src/future.c index b5254ebec3..9125636e8c 100644 --- a/src/racket/src/future.c +++ b/src/racket/src/future.c @@ -303,8 +303,10 @@ static void requeue_future(struct future_t *future, struct Scheme_Future_State * static void future_do_runtimecall(Scheme_Future_Thread_State *fts, void *func, int is_atomic, - int can_suspend); -static int capture_future_continuation(struct Scheme_Future_State *fs, future_t *ft, void **storage, int need_lock); + int can_suspend, + int for_overflow); +static int capture_future_continuation(struct Scheme_Future_State *fs, future_t *ft, void **storage, + int need_lock, int for_overflow); #define FUTURE_C_STACK_SIZE 500000 #define FUTURE_RUNSTACK_SIZE 2000 @@ -316,6 +318,7 @@ enum { FEVENT_COMPLETE, FEVENT_START_WORK, FEVENT_START_RTONLY_WORK, + FEVENT_RESUME_WORK, FEVENT_END_WORK, FEVENT_RTCALL_ATOMIC, FEVENT_HANDLE_RTCALL_ATOMIC, @@ -327,6 +330,7 @@ enum { FEVENT_RTCALL_ABORT, FEVENT_HANDLE_RTCALL_ABORT, FEVENT_RTCALL_SUSPEND, + FEVENT_OVERFLOW, FEVENT_TOUCH_PAUSE, FEVENT_TOUCH_RESUME, FEVENT_MISSING, @@ -334,18 +338,20 @@ enum { }; static const char * const fevent_strs[] = { "create", "complete", - "start-work", "start-0-work", "end-work", + "start-work", "start-0-work", "start-overflow-work", + "end-work", "sync", "sync", "block", "touch", "block", "result", "result", "abort", "abort", - "suspend", + "suspend", "overflow", "touch-pause", "touch-resume", "missing" }; static const char * const fevent_long_strs[] = { "created", "completed", - "started work", "started (process 0, only)", "ended work", + "started work", "started (process 0, only)", "started (overflow)", + "ended work", "synchronizing with process 0", "synchronizing", "BLOCKING on process 0", "touching future", "HANDLING", "result from process 0", "result determined", "abort from process 0", "abort determined", - "suspended", + "suspended", "overflow", "paused for touch", "resumed for touch", "events missing" }; @@ -384,7 +390,7 @@ typedef struct Scheme_Future_State { THREAD_LOCAL_DECL(static Scheme_Future_State *scheme_future_state); -THREAD_LOCAL_DECL(void *jit_future_storage[2]); +THREAD_LOCAL_DECL(void *jit_future_storage[4]); #ifdef MZ_PRECISE_GC THREAD_LOCAL_DECL(extern uintptr_t GC_gen0_alloc_page_ptr); @@ -408,8 +414,13 @@ static Scheme_Object *apply_future_lw(future_t *ft); static int fsemaphore_ready(Scheme_Object *obj); static void init_fevent(Fevent_Buffer *b); static void free_fevent(Fevent_Buffer *b); -static void future_in_runtime(Scheme_Future_State *fs, future_t * volatile ft, int what); +static int future_in_runtime(Scheme_Future_State *fs, future_t * volatile ft, int what); static Scheme_Object *would_be_future(int argc, Scheme_Object *argv[]); +static void push_suspended_lw(Scheme_Future_State *fs, future_t *ft); +static void pop_suspended_lw(Scheme_Future_State *fs, future_t *ft); + +static Scheme_Object *bad_multi_result_proc; +static Scheme_Object *bad_multi_result(int argc, Scheme_Object **argv); READ_ONLY static int cpucount; static void init_cpucount(void); @@ -543,6 +554,9 @@ void scheme_init_futures(Scheme_Env *newenv) void scheme_init_futures_once() { init_cpucount(); + + REGISTER_SO(bad_multi_result_proc); + bad_multi_result_proc = scheme_make_prim(bad_multi_result); } void scheme_init_futures_per_place() @@ -664,7 +678,7 @@ static void init_future_thread(Scheme_Future_State *fs, int i) scheme_register_static(params.scheme_current_runstack_ptr, sizeof(void*)); scheme_register_static(params.scheme_current_runstack_start_ptr, sizeof(void*)); - scheme_register_static(params.jit_future_storage_ptr, 2 * sizeof(void*)); + scheme_register_static(params.jit_future_storage_ptr, 4 * sizeof(void*)); scheme_register_static(params.current_thread_ptr, sizeof(void*)); fs->pool_threads[i] = fts; @@ -1205,8 +1219,6 @@ static Scheme_Object *make_future(Scheme_Object *lambda, int enqueue) /* Can't even call it in a future thread */ ft->status = PENDING_OVERSIZE; } - - ft->code = (void*)ncd->start_code; } else ft->status = PENDING_OVERSIZE; @@ -1226,6 +1238,12 @@ static Scheme_Object *make_future(Scheme_Object *lambda, int enqueue) return (Scheme_Object*)ft; } +int scheme_can_apply_native_in_future(Scheme_Object *proc) + XFORM_SKIP_PROC /* can be called from future thread */ +{ + return (((Scheme_Native_Closure *)proc)->code->max_let_depth < FUTURE_RUNSTACK_SIZE * sizeof(void*)); +} + static Scheme_Object *do_make_future(int argc, Scheme_Object *argv[]) { scheme_check_proc_arity("future", 0, 0, argc, argv); @@ -1244,7 +1262,7 @@ Scheme_Object *scheme_future(int argc, Scheme_Object *argv[]) if (SAME_TYPE(SCHEME_TYPE(proc), scheme_native_closure_type) && scheme_native_arity_check(proc, 0) && (((Scheme_Native_Closure *)proc)->code->start_code != scheme_on_demand_jit_code) - && (((Scheme_Native_Closure *)proc)->code->max_let_depth < FUTURE_RUNSTACK_SIZE * sizeof(void*))) { + && scheme_can_apply_native_in_future(proc)) { /* try to alocate a future in the future thread */ future_t *ft; ft = MALLOC_ONE_TAGGED(future_t); @@ -1255,7 +1273,6 @@ Scheme_Object *scheme_future(int argc, Scheme_Object *argv[]) ft->orig_lambda = proc; ft->status = PENDING; ft->cust = scheme_current_thread->current_ft->cust; - ft->code = ((Scheme_Native_Closure *)proc)->code->start_code; mzrt_mutex_lock(fs->future_mutex); ft->id = ++fs->next_futureid; @@ -1490,7 +1507,7 @@ Scheme_Object *scheme_fsemaphore_wait(int argc, Scheme_Object **argv) fsemaphore_t *sema; Scheme_Future_Thread_State *fts = scheme_future_thread_state; Scheme_Future_State *fs = scheme_future_state; - void *storage[3]; + void *storage[4]; if (!SAME_TYPE(SCHEME_TYPE(argv[0]), scheme_fsemaphore_type)) { SCHEME_WRONG_CONTRACT_MAYBE_IN_FT("fsemaphore-wait", "fsemaphore?", 0, argc, argv); @@ -1541,7 +1558,7 @@ Scheme_Object *scheme_fsemaphore_wait(int argc, Scheme_Object **argv) /* Try to capture it locally (on this thread) */ if (GC_gen0_alloc_page_ptr - && capture_future_continuation(fs, future, storage, 0)) { + && capture_future_continuation(fs, future, storage, 0, 0)) { /* capture sets fts->thread->current_ft to NULL */ mzrt_mutex_lock(fs->future_mutex); } else { @@ -1759,12 +1776,13 @@ static Scheme_Object *shallower_apply_future_lw_k(void) return apply_future_lw(ft); } -static void future_in_runtime(Scheme_Future_State *fs, future_t * volatile ft, int what) -{ +static int future_in_runtime(Scheme_Future_State *fs, future_t * volatile ft, int what) +{ mz_jmp_buf newbuf, * volatile savebuf; Scheme_Thread *p = scheme_current_thread; Scheme_Object * volatile retval; future_t * volatile old_ft; + int done; old_ft = p->current_ft; p->current_ft = ft; @@ -1785,7 +1803,25 @@ static void future_in_runtime(Scheme_Future_State *fs, future_t * volatile ft, i } else retval = apply_future_lw(ft); } else { - retval = scheme_apply_multi(ft->orig_lambda, 0, NULL); + if (ft->suspended_lw_stack) { + Scheme_Object *rator, **argv; + int argc; + Scheme_Lightweight_Continuation *lc; + rator = (Scheme_Object *)ft->suspended_lw_stack[2]; + argc = SCHEME_INT_VAL((Scheme_Object *)ft->suspended_lw_stack[3]); + argv = (Scheme_Object **)ft->suspended_lw_stack[4]; + ft->suspended_lw_stack[2] = NULL; + ft->suspended_lw_stack[4] = NULL; + + lc = (Scheme_Lightweight_Continuation *)ft->suspended_lw_stack[1]; + scheme_restore_lightweight_continuation_marks(lc); + + if (ft->suspended_lw_stack[5]) + retval = _scheme_apply_multi(rator, argc, argv); + else + retval = _scheme_apply(rator, argc, argv); + } else + retval = scheme_apply_multi(ft->orig_lambda, 0, NULL); } send_special_result(ft, retval); } @@ -1796,17 +1832,27 @@ static void future_in_runtime(Scheme_Future_State *fs, future_t * volatile ft, i ft->retval = retval; mzrt_mutex_lock(fs->future_mutex); - ft->status = FINISHED; - trigger_added_touches(fs, ft); - mzrt_mutex_unlock(fs->future_mutex); + if (ft->suspended_lw_stack && retval) { + pop_suspended_lw(fs, ft); + done = 0; + } else { + if (!retval) + ft->suspended_lw_stack = NULL; + ft->status = FINISHED; + trigger_added_touches(fs, ft); + done = 1; + } record_fevent(FEVENT_COMPLETE, ft->id); + mzrt_mutex_unlock(fs->future_mutex); record_fevent(FEVENT_END_WORK, ft->id); if (!retval) { scheme_longjmp(*savebuf, 1); } + + return done; } static int prefer_to_apply_future_in_runtime() @@ -1851,18 +1897,21 @@ Scheme_Object *general_touch(int argc, Scheme_Object *argv[]) what = FEVENT_START_RTONLY_WORK; } else if (ft->status != SUSPENDED) { dequeue_future(fs, ft); + if (ft->suspended_lw_stack) + what = FEVENT_RESUME_WORK; } ft->status = RUNNING; mzrt_mutex_unlock(fs->future_mutex); if (ft->in_tracing_mode) { run_would_be_future(ft); + retval = ft->retval; + break; } else { - future_in_runtime(fs, ft, what); + if (future_in_runtime(fs, ft, what)) { + retval = ft->retval; + break; + } } - - retval = ft->retval; - - break; } else if ((ft->status == RUNNING) || (ft->status == WAITING_FOR_FSEMA) @@ -1900,7 +1949,7 @@ Scheme_Object *general_touch(int argc, Scheme_Object *argv[]) ft->status = RUNNING; /* may raise an exception or escape: */ mzrt_mutex_unlock(fs->future_mutex); - future_in_runtime(fs, ft, FEVENT_START_WORK); + (void)future_in_runtime(fs, ft, FEVENT_START_WORK); } else { /* Someone needs to handle the future. We're banking on some future thread eventually picking up the future, which is @@ -2079,7 +2128,7 @@ void *worker_thread_future_loop(void *arg) Scheme_Native_Proc *jitcode; future_t *ft; mz_jmp_buf newbuf; - int fid; + int fid, what; scheme_future_state = fs; scheme_future_thread_state = fts; @@ -2137,8 +2186,13 @@ void *worker_thread_future_loop(void *arg) if (ft) { fs->busy_thread_count++; + + if (ft->suspended_lw_stack) + what = FEVENT_RESUME_WORK; + else + what = FEVENT_START_WORK; fid = ft->id; - record_fevent(FEVENT_START_WORK, fid); + record_fevent(what, fid); /* Work is available for this thread */ ft->status = RUNNING; @@ -2166,8 +2220,6 @@ void *worker_thread_future_loop(void *arg) v = _apply_future_lw(ft); } } else { - jitcode = ft->code; - /* Run the code: The lambda passed to a future will always be a parameterless function. @@ -2182,8 +2234,30 @@ void *worker_thread_future_loop(void *arg) /* failed or suspended */ v = NULL; } else { + Scheme_Object *rator, **argv; + int argc; + + if (ft->suspended_lw_stack) { + Scheme_Lightweight_Continuation *lc; + + lc = (Scheme_Lightweight_Continuation *)ft->suspended_lw_stack[1]; + scheme_restore_lightweight_continuation_marks(lc); /* might trigger GC */ + ft = fts->thread->current_ft; + + rator = (Scheme_Object *)ft->suspended_lw_stack[2]; + argc = SCHEME_INT_VAL((Scheme_Object *)ft->suspended_lw_stack[3]); + argv = (Scheme_Object **)ft->suspended_lw_stack[4]; + ft->suspended_lw_stack[2] = NULL; + ft->suspended_lw_stack[4] = NULL; + } else { + rator = ft->orig_lambda; + argc = 0; + argv = NULL; + } + scheme_fill_lwc_start(); - v = scheme_call_as_lightweight_continuation(jitcode, ft->orig_lambda, 0, NULL); + jitcode = ((Scheme_Native_Closure *)rator)->code->start_code; + v = scheme_call_as_lightweight_continuation(jitcode, rator, argc, argv); if (SAME_OBJ(v, SCHEME_TAIL_CALL_WAITING)) { v = scheme_ts_scheme_force_value_same_mark(v); } @@ -2205,15 +2279,29 @@ void *worker_thread_future_loop(void *arg) if (ft->no_retval >= 0) { /* Set the return val in the descriptor */ ft->retval = v; - /* In case of multiple values: */ send_special_result(ft, v); - - /* Update the status */ - ft->status = FINISHED; - trigger_added_touches(fs, ft); + if (ft->suspended_lw_stack) { + if (!ft->suspended_lw_stack[5] && SAME_OBJ(v, SCHEME_MULTIPLE_VALUES)) { + /* multiple results are not allowed; keep the same lw stack, + but replace the function to call: */ + ft->status = PENDING_OVERSIZE; + ft->suspended_lw_stack[2] = bad_multi_result_proc; + ft->suspended_lw_stack[3] = scheme_make_integer(ft->multiple_count); + ft->suspended_lw_stack[4] = ft->multiple_array; + ft->retval_s = NULL; + ft->multiple_array = NULL; + } else + pop_suspended_lw(fs, ft); + } else { + /* Update the status */ + ft->status = FINISHED; + trigger_added_touches(fs, ft); + } record_fevent(FEVENT_COMPLETE, fid); + } else { + ft->suspended_lw_stack = NULL; } fts->thread->current_ft = NULL; @@ -2290,7 +2378,8 @@ static Scheme_Object *apply_future_lw(future_t *ft) return (Scheme_Object *)scheme_top_level_do(apply_future_lw_k, 0); } -static int capture_future_continuation(Scheme_Future_State *fs, future_t *ft, void **storage, int need_lock) +static int capture_future_continuation(Scheme_Future_State *fs, future_t *ft, void **storage, + int need_lock, int for_overflow) XFORM_SKIP_PROC /* The lock is *not* held when calling this function. This function explicitly cooperates with the GC by storing the @@ -2300,13 +2389,23 @@ static int capture_future_continuation(Scheme_Future_State *fs, future_t *ft, vo { Scheme_Lightweight_Continuation *lw; Scheme_Object **arg_S; + void **stack; storage[2] = ft; + if (for_overflow) { + stack = MALLOC_N(void*, 6); + if (!stack) return 0; + storage[3] = stack; + ft = (future_t *)storage[2]; + } else + stack = NULL; + lw = scheme_capture_lightweight_continuation(ft->fts->thread, ft->lwc, storage); if (!lw) return 0; ft = (future_t *)storage[2]; + stack = (void **)storage[3]; if (need_lock) { mzrt_mutex_lock(fs->future_mutex); @@ -2342,9 +2441,48 @@ static int capture_future_continuation(Scheme_Future_State *fs, future_t *ft, vo ft->arg_S2 = arg_S; } + if (for_overflow) { + stack[0] = ft->suspended_lw_stack; + stack[5] = ((for_overflow > 1) ? scheme_true : NULL); + ft->suspended_lw_stack = stack; + } + return 1; } +static void push_suspended_lw(Scheme_Future_State *fs, future_t *ft) + XFORM_SKIP_PROC +/* called in any thread; needs lock */ +{ + ft->suspended_lw_stack[1] = ft->suspended_lw; + ft->suspended_lw = NULL; + + ft->suspended_lw_stack[2] = ft->arg_s0; + ft->arg_s0 = NULL; + ft->suspended_lw_stack[3] = scheme_make_integer(ft->arg_i0); + ft->suspended_lw_stack[4] = ft->arg_S0; + ft->arg_S0 = NULL; + + ft->status = PENDING; + (void)enqueue_future(fs, ft); +} + +static void pop_suspended_lw(Scheme_Future_State *fs, future_t *ft) + XFORM_SKIP_PROC +/* called in any thread; needs lock */ +{ + ft->retval_s = ft->retval; + ft->retval = NULL; + + ft->suspended_lw = (Scheme_Lightweight_Continuation *)ft->suspended_lw_stack[1]; + ft->maybe_suspended_lw = 1; + + ft->suspended_lw_stack = (void **)ft->suspended_lw_stack[0]; + + ft->status = PENDING; + (void)enqueue_future(fs, ft); +} + void scheme_check_future_work() /* Called in the runtime thread by the scheduler */ { @@ -2448,14 +2586,21 @@ void scheme_check_future_work() mzrt_mutex_unlock(fs->future_mutex); if (ft) { - void *storage[3]; + void *storage[4]; - if (capture_future_continuation(fs, ft, storage, 1)) { + if (capture_future_continuation(fs, ft, storage, 1, + ((ft->status == WAITING_FOR_OVERFLOW) + ? ft->arg_i1 + : 0))) { /* capture performs mzrt_mutex_lock(fs->future_mutex) on success. */ - if (ft->suspended_lw) - FUTURE_ASSERT((ft->status == WAITING_FOR_PRIM) - || (ft->status == WAITING_FOR_FSEMA)); - else + if (ft->suspended_lw) { + FUTURE_ASSERT((ft->status == WAITING_FOR_PRIM) + || (ft->status == WAITING_FOR_FSEMA) + || (ft->status == WAITING_FOR_OVERFLOW)); + if (ft->status == WAITING_FOR_OVERFLOW) { + push_suspended_lw(fs, ft); + } + } else FUTURE_ASSERT(ft->status != RUNNING); mzrt_mutex_unlock(fs->future_mutex); } else { @@ -2503,7 +2648,8 @@ void scheme_check_future_work() static void future_do_runtimecall(Scheme_Future_Thread_State *fts, void *func, int is_atomic, - int can_suspend) + int can_suspend, + int for_overflow) XFORM_SKIP_PROC /* Called in either future or runtime thread. Can only be called in the runtime thread if we are in slow-path trace mode (i.e. we are running a future that is bound to the @@ -2511,7 +2657,7 @@ static void future_do_runtimecall(Scheme_Future_Thread_State *fts, { future_t *future; Scheme_Future_State *fs = scheme_future_state; - void *storage[3]; + void *storage[4]; int insist_to_suspend, prefer_to_suspend, fid; /* Fetch the future descriptor for this thread */ @@ -2534,7 +2680,8 @@ static void future_do_runtimecall(Scheme_Future_Thread_State *fts, fid = future->id; - /* Policy question: When should the future thread suspend + /* If for_overflow, then a suspend is required. Otherwise... + Policy question: When should the future thread suspend the current future? It costs something to suspend and resume a future. The current policy: @@ -2544,7 +2691,7 @@ static void future_do_runtimecall(Scheme_Future_Thread_State *fts, more work available in the future queue, and only if we can suspend ourselves (because asking the runtime thread to suspend wouldn't accomplish anything). */ - insist_to_suspend = !is_atomic; + insist_to_suspend = !is_atomic || for_overflow; prefer_to_suspend = (insist_to_suspend || fs->future_queue_count); if (!scheme_custodian_is_available(future->cust)) { @@ -2559,7 +2706,7 @@ static void future_do_runtimecall(Scheme_Future_Thread_State *fts, if (prefer_to_suspend && GC_gen0_alloc_page_ptr - && capture_future_continuation(fs, future, storage, 0)) { + && capture_future_continuation(fs, future, storage, 0, for_overflow)) { /* this future thread will suspend handling the future continuation until the result of the blocking call is ready; fts->thread->current_ft was set to NULL */ @@ -2567,17 +2714,29 @@ static void future_do_runtimecall(Scheme_Future_Thread_State *fts, mzrt_mutex_lock(fs->future_mutex); - if (func == touch) { + if (for_overflow) { + record_fevent(FEVENT_OVERFLOW, fid); + } else if (func == touch) { record_fevent(FEVENT_RTCALL_TOUCH, fid); } else { record_fevent(is_atomic ? FEVENT_RTCALL_ATOMIC : FEVENT_RTCALL, fid); } - /* Set up the arguments for the runtime call - to be picked up by the main rt thread */ - future->prim_func = func; - future->rt_prim_is_atomic = is_atomic; - future->status = WAITING_FOR_PRIM; + if (for_overflow) { + if (!fts->thread->current_ft) { + /* capture complete; re-enqueue so that it continues on fresh stack */ + push_suspended_lw(fs, future); + } else { + future->status = WAITING_FOR_OVERFLOW; + future->arg_i1 = for_overflow; + } + } else { + /* Set up the arguments for the runtime call + to be picked up by the main rt thread */ + future->prim_func = func; + future->rt_prim_is_atomic = is_atomic; + future->status = WAITING_FOR_PRIM; + } if (is_atomic) { future->next_waiting_atomic = fs->future_waiting_atomic; @@ -2594,6 +2753,8 @@ static void future_do_runtimecall(Scheme_Future_Thread_State *fts, future->in_queue_waiting_for_lwc = 1; } future->want_lw = 1; + /* In case of for_overflow, runtime thread is responsible for + enqueuing the future to continue. */ } } @@ -2631,6 +2792,7 @@ static void future_do_runtimecall(Scheme_Future_Thread_State *fts, future = fts->thread->current_ft; FUTURE_ASSERT(!future || !future->can_continue_sema); + FUTURE_ASSERT(!future || !for_overflow); if (future) { future->want_lw = 0; @@ -2644,7 +2806,8 @@ static void future_do_runtimecall(Scheme_Future_Thread_State *fts, future->status = RUNNING; } } else { - record_fevent(FEVENT_RTCALL_SUSPEND, fid); + if (!for_overflow) + record_fevent(FEVENT_RTCALL_SUSPEND, fid); } mzrt_mutex_unlock(fs->future_mutex); @@ -2661,6 +2824,12 @@ static void future_do_runtimecall(Scheme_Future_Thread_State *fts, } } +static Scheme_Object *bad_multi_result(int argc, Scheme_Object **argv) +{ + scheme_wrong_return_arity(NULL, 1, argc, argv, NULL); + return NULL; +} + /**********************************************************************/ /* Functions for primitive invocation */ /**********************************************************************/ @@ -2680,7 +2849,7 @@ void scheme_wrong_contract_from_ft(const char *who, const char *expected_type, i future->time_of_request = get_future_timestamp(); future->source_of_request = who; - future_do_runtimecall(fts, NULL, 0, 1); + future_do_runtimecall(fts, NULL, 0, 1, 0); /* Fetch the future again, in case moved by a GC */ future = fts->thread->current_ft; @@ -2709,7 +2878,7 @@ Scheme_Object **scheme_rtcall_on_demand(Scheme_Object **argv) future->source_of_request = "[jit_on_demand]"; future->source_type = FSRC_OTHER; - future_do_runtimecall(fts, NULL, 1, 1); + future_do_runtimecall(fts, NULL, 1, 1, 0); /* Fetch the future again, in case moved by a GC */ future = fts->thread->current_ft; @@ -2743,7 +2912,7 @@ Scheme_Object *scheme_rtcall_make_fsemaphore(Scheme_Object *ready) else is_atomic = 0; - future_do_runtimecall(fts, NULL, is_atomic, 1); + future_do_runtimecall(fts, NULL, is_atomic, 1, 0); /* Fetch the future again, in case moved by a GC */ future = fts->thread->current_ft; @@ -2774,7 +2943,7 @@ Scheme_Object *scheme_rtcall_make_future(Scheme_Object *proc) future->source_of_request = "future"; future->source_type = FSRC_OTHER; - future_do_runtimecall(fts, NULL, is_atomic, 1); + future_do_runtimecall(fts, NULL, is_atomic, 1, 0); /* Fetch the future again, in case moved by a GC */ future = fts->thread->current_ft; @@ -2801,7 +2970,7 @@ void scheme_rtcall_allocate_values(int count, Scheme_Thread *t) future->source_of_request = "[allocate_values]"; future->source_type = FSRC_OTHER; - future_do_runtimecall(fts, NULL, 1, 0); + future_do_runtimecall(fts, NULL, 1, 0, 0); /* Fetch the future again, in case moved by a GC */ future = fts->thread->current_ft; @@ -2827,7 +2996,43 @@ Scheme_Object *scheme_rtcall_tail_apply(Scheme_Object *rator, int argc, Scheme_O future->source_of_request = "[tail-call]"; future->source_type = FSRC_OTHER; - future_do_runtimecall(fts, NULL, 1, 0); + future_do_runtimecall(fts, NULL, 1, 0, 0); + + /* Fetch the future again, in case moved by a GC */ + future = fts->thread->current_ft; + + future->arg_s0 = NULL; + future->arg_S0 = NULL; + + retval = future->retval_s; + future->retval_s = NULL; + + receive_special_result(future, retval, 1); + + return retval; +} + +Scheme_Object *scheme_rtcall_apply_with_new_stack(Scheme_Object *rator, int argc, Scheme_Object **argv, + int multi) + XFORM_SKIP_PROC +/* Called in future thread; rator is a native closure with a runstack limit that fits */ +{ + Scheme_Future_Thread_State *fts = scheme_future_thread_state; + future_t *future = fts->thread->current_ft; + Scheme_Object *retval; + + future->prim_protocol = SIG_APPLY_AFRESH; + + future->arg_s0 = rator; + future->arg_i0 = argc; + future->arg_S0 = argv; + future->arg_i1 = multi; + + future->time_of_request = get_future_timestamp(); + future->source_of_request = "[stack-overflow]"; + future->source_type = FSRC_OTHER; + + future_do_runtimecall(fts, NULL, 1, 1, (multi ? 2 : 1)); /* Fetch the future again, in case moved by a GC */ future = fts->thread->current_ft; @@ -2883,7 +3088,7 @@ uintptr_t scheme_rtcall_alloc() future->prim_protocol = SIG_ALLOC; future->arg_i0 = fts->gen0_size; - future_do_runtimecall(fts, NULL, 1, 0); + future_do_runtimecall(fts, NULL, 1, 0, 0); future = fts->thread->current_ft; retval = future->alloc_retval; @@ -2919,7 +3124,7 @@ void scheme_rtcall_new_mark_segment(Scheme_Thread *p) future->prim_protocol = SIG_ALLOC_MARK_SEGMENT; future->arg_s0 = (Scheme_Object *)p; - future_do_runtimecall(fts, NULL, 1, 0); + future_do_runtimecall(fts, NULL, 1, 0, 0); } static int push_marks(future_t *f, Scheme_Cont_Frame_Data *d) @@ -3033,7 +3238,7 @@ static void do_invoke_rtcall(Scheme_Future_State *fs, future_t *future) flush_future_logs(fs); - /* use lg_future_event so we can include `str' in the message: */ + /* use log_future_event so we can include `str' in the message: */ log_future_event(fs, "future %d, process %d: %s: %s; time: %f", src, @@ -3153,6 +3358,28 @@ static void do_invoke_rtcall(Scheme_Future_State *fs, future_t *future) /* doesn't return */ + break; + } + case SIG_APPLY_AFRESH: + { + GC_CAN_IGNORE Scheme_Object *arg_s0 = future->arg_s0; + GC_CAN_IGNORE Scheme_Object **arg_S0 = future->arg_S0; + GC_CAN_IGNORE Scheme_Object *retval; + + /* This code is used only for would-be futures: */ + FUTURE_ASSERT(future->in_tracing_mode); + + future->arg_s0 = NULL; + future->arg_S0 = NULL; + + if (future->arg_i1) + retval = _scheme_apply_multi(arg_s0, future->arg_i0, arg_S0); + else + retval = _scheme_apply(arg_s0, future->arg_i0, arg_S0); + + future->retval_s = retval; + send_special_result(future, retval); + break; } # define JIT_TS_LOCALIZE(t, f) GC_CAN_IGNORE t f = future->f diff --git a/src/racket/src/future.h b/src/racket/src/future.h index 0be73e1572..892a1f0abb 100644 --- a/src/racket/src/future.h +++ b/src/racket/src/future.h @@ -8,14 +8,27 @@ typedef Scheme_Object* (*prim_int_pobj_obj_t)(int, Scheme_Object**); typedef Scheme_Object* (*prim_int_pobj_obj_obj_t)(int, Scheme_Object**, Scheme_Object*); typedef void* (*prim_pvoid_pvoid_pvoid_t)(void*, void*); +/* PENDING is ready to run: */ #define PENDING 0 +/* RUNNING is running in some thread: */ #define RUNNING 1 +/* WAITING_FOR_PRIM is waiting for the runtime thread to start runnin + a primitive -- possibiliy atomic, possibly not, and possibly a LWC + capture happens while waiting: */ #define WAITING_FOR_PRIM 2 +/* FINISHED means the result (or failure) is ready: */ #define FINISHED 3 +/* PENDING is ready to run, but won't work in a future thread: */ #define PENDING_OVERSIZE 4 +/* WAITING_FOR_PRIM is the runtime thread working on a primitive: */ #define HANDLING_PRIM 5 +/* WAITING_FOR_FSEMA is in the queue of an fsemaphore: */ #define WAITING_FOR_FSEMA 6 +/* SUSPENDED is the owning custodian is gone, so the future will never finish: */ #define SUSPENDED 7 +/* WAITING_FOR_OVERFLOW is waiting for an LCW capture to continue + for a stack overflow: */ +#define WAITING_FOR_OVERFLOW 8 /* FSRC_OTHER means: descriptive string is provided for logging, called function *DOES NOT NEED* to lookup continuation marks. */ @@ -88,7 +101,6 @@ typedef struct future_t { that case */ Scheme_Object *orig_lambda; - void *code; Scheme_Custodian *cust; /* an approximate custodian; don't use a future thread if this custodian is shut down */ @@ -178,6 +190,8 @@ typedef struct future_t { extra flag avoids spinning if the suspended continuation cannot be resumed in the main thread for some reason */ + void **suspended_lw_stack; /* for overflow handling */ + Scheme_Object *retval_s; void *retval_p; /* use only with conservative GC */ MZ_MARK_STACK_TYPE retval_m; @@ -228,6 +242,7 @@ typedef struct fsemaphore_t { #define SIG_FUTURE 6 #define SIG_WRONG_TYPE_EXN 7 #define SIG_TAIL_APPLY 8 +#define SIG_APPLY_AFRESH 9 # include "jit_ts_protos.h" @@ -240,6 +255,9 @@ extern void scheme_rtcall_allocate_values(int count, Scheme_Thread *t); extern Scheme_Object *scheme_rtcall_make_fsemaphore(Scheme_Object *ready); extern Scheme_Object *scheme_rtcall_make_future(Scheme_Object *proc); extern Scheme_Object *scheme_rtcall_tail_apply(Scheme_Object *rator, int argc, Scheme_Object **argv); +extern Scheme_Object *scheme_rtcall_apply_with_new_stack(Scheme_Object *rator, int argc, Scheme_Object **argv, int multi); + +int scheme_can_apply_native_in_future(Scheme_Object *proc); void scheme_future_block_until_gc(); void scheme_future_continue_after_gc(); diff --git a/src/racket/src/gen-jit-ts.rkt b/src/racket/src/gen-jit-ts.rkt index 516db67fe9..c57288f6e4 100644 --- a/src/racket/src/gen-jit-ts.rkt +++ b/src/racket/src/gen-jit-ts.rkt @@ -98,7 +98,7 @@ @string-append{ future->arg_@|(string t)|@|(number->string i)| = @|a|;}) "\n") @(if (equal? arg-types '("Scheme_Object*")) @string-append{send_special_result(future, @(car arg-names));} "") - future_do_runtimecall(fts, (void*)f, 0, 1); + future_do_runtimecall(fts, (void*)f, 0, 1, 0); fts->thread = scheme_current_thread; future = fts->thread->current_ft; @(if (string=? result-type "void") "" @string-append{retval = @|fretval|;}) diff --git a/src/racket/src/jit_ts_def.c b/src/racket/src/jit_ts_def.c index 1402bd5578..f0b054f2b0 100644 --- a/src/racket/src/jit_ts_def.c +++ b/src/racket/src/jit_ts_def.c @@ -1,38 +1,38 @@ #define define_ts_siS_s(id, src_type) \ -static Scheme_Object* ts_ ## id(Scheme_Object* g5, int g6, Scheme_Object** g7) \ +static Scheme_Object* ts_ ## id(Scheme_Object* g7, int g8, Scheme_Object** g9) \ XFORM_SKIP_PROC \ { \ if (scheme_use_rtcall) \ - return scheme_rtcall_siS_s("[" #id "]", src_type, id, g5, g6, g7); \ + return scheme_rtcall_siS_s("[" #id "]", src_type, id, g7, g8, g9); \ else \ - return id(g5, g6, g7); \ + return id(g7, g8, g9); \ } #define define_ts_iSs_s(id, src_type) \ -static Scheme_Object* ts_ ## id(int g8, Scheme_Object** g9, Scheme_Object* g10) \ +static Scheme_Object* ts_ ## id(int g10, Scheme_Object** g11, Scheme_Object* g12) \ XFORM_SKIP_PROC \ { \ if (scheme_use_rtcall) \ - return scheme_rtcall_iSs_s("[" #id "]", src_type, id, g8, g9, g10); \ + return scheme_rtcall_iSs_s("[" #id "]", src_type, id, g10, g11, g12); \ else \ - return id(g8, g9, g10); \ + return id(g10, g11, g12); \ } #define define_ts_s_s(id, src_type) \ -static Scheme_Object* ts_ ## id(Scheme_Object* g11) \ +static Scheme_Object* ts_ ## id(Scheme_Object* g13) \ XFORM_SKIP_PROC \ { \ if (scheme_use_rtcall) \ - return scheme_rtcall_s_s("[" #id "]", src_type, id, g11); \ + return scheme_rtcall_s_s("[" #id "]", src_type, id, g13); \ else \ - return id(g11); \ + return id(g13); \ } #define define_ts_n_s(id, src_type) \ -static Scheme_Object* ts_ ## id(Scheme_Native_Closure_Data* g12) \ +static Scheme_Object* ts_ ## id(Scheme_Native_Closure_Data* g14) \ XFORM_SKIP_PROC \ { \ if (scheme_use_rtcall) \ - return scheme_rtcall_n_s("[" #id "]", src_type, id, g12); \ + return scheme_rtcall_n_s("[" #id "]", src_type, id, g14); \ else \ - return id(g12); \ + return id(g14); \ } #define define_ts__s(id, src_type) \ static Scheme_Object* ts_ ## id() \ @@ -44,200 +44,200 @@ static Scheme_Object* ts_ ## id() \ return id(); \ } #define define_ts_ss_s(id, src_type) \ -static Scheme_Object* ts_ ## id(Scheme_Object* g13, Scheme_Object* g14) \ +static Scheme_Object* ts_ ## id(Scheme_Object* g15, Scheme_Object* g16) \ XFORM_SKIP_PROC \ { \ if (scheme_use_rtcall) \ - return scheme_rtcall_ss_s("[" #id "]", src_type, id, g13, g14); \ + return scheme_rtcall_ss_s("[" #id "]", src_type, id, g15, g16); \ else \ - return id(g13, g14); \ + return id(g15, g16); \ } #define define_ts_ssi_s(id, src_type) \ -static Scheme_Object* ts_ ## id(Scheme_Object* g15, Scheme_Object* g16, int g17) \ +static Scheme_Object* ts_ ## id(Scheme_Object* g17, Scheme_Object* g18, int g19) \ XFORM_SKIP_PROC \ { \ if (scheme_use_rtcall) \ - return scheme_rtcall_ssi_s("[" #id "]", src_type, id, g15, g16, g17); \ + return scheme_rtcall_ssi_s("[" #id "]", src_type, id, g17, g18, g19); \ else \ - return id(g15, g16, g17); \ + return id(g17, g18, g19); \ } #define define_ts_tt_s(id, src_type) \ -static Scheme_Object* ts_ ## id(const Scheme_Object* g18, const Scheme_Object* g19) \ +static Scheme_Object* ts_ ## id(const Scheme_Object* g20, const Scheme_Object* g21) \ XFORM_SKIP_PROC \ { \ if (scheme_use_rtcall) \ - return scheme_rtcall_tt_s("[" #id "]", src_type, id, g18, g19); \ - else \ - return id(g18, g19); \ -} -#define define_ts_ss_m(id, src_type) \ -static MZ_MARK_STACK_TYPE ts_ ## id(Scheme_Object* g20, Scheme_Object* g21) \ - XFORM_SKIP_PROC \ -{ \ - if (scheme_use_rtcall) \ - return scheme_rtcall_ss_m("[" #id "]", src_type, id, g20, g21); \ + return scheme_rtcall_tt_s("[" #id "]", src_type, id, g20, g21); \ else \ return id(g20, g21); \ } -#define define_ts_Sl_s(id, src_type) \ -static Scheme_Object* ts_ ## id(Scheme_Object** g22, intptr_t g23) \ +#define define_ts_ss_m(id, src_type) \ +static MZ_MARK_STACK_TYPE ts_ ## id(Scheme_Object* g22, Scheme_Object* g23) \ XFORM_SKIP_PROC \ { \ if (scheme_use_rtcall) \ - return scheme_rtcall_Sl_s("[" #id "]", src_type, id, g22, g23); \ + return scheme_rtcall_ss_m("[" #id "]", src_type, id, g22, g23); \ else \ return id(g22, g23); \ } -#define define_ts_l_s(id, src_type) \ -static Scheme_Object* ts_ ## id(intptr_t g24) \ +#define define_ts_Sl_s(id, src_type) \ +static Scheme_Object* ts_ ## id(Scheme_Object** g24, intptr_t g25) \ XFORM_SKIP_PROC \ { \ if (scheme_use_rtcall) \ - return scheme_rtcall_l_s("[" #id "]", src_type, id, g24); \ + return scheme_rtcall_Sl_s("[" #id "]", src_type, id, g24, g25); \ else \ - return id(g24); \ + return id(g24, g25); \ +} +#define define_ts_l_s(id, src_type) \ +static Scheme_Object* ts_ ## id(intptr_t g26) \ + XFORM_SKIP_PROC \ +{ \ + if (scheme_use_rtcall) \ + return scheme_rtcall_l_s("[" #id "]", src_type, id, g26); \ + else \ + return id(g26); \ } #define define_ts_bsi_v(id, src_type) \ -static void ts_ ## id(Scheme_Bucket* g25, Scheme_Object* g26, int g27) \ +static void ts_ ## id(Scheme_Bucket* g27, Scheme_Object* g28, int g29) \ XFORM_SKIP_PROC \ { \ if (scheme_use_rtcall) \ - scheme_rtcall_bsi_v("[" #id "]", src_type, id, g25, g26, g27); \ + scheme_rtcall_bsi_v("[" #id "]", src_type, id, g27, g28, g29); \ else \ - id(g25, g26, g27); \ + id(g27, g28, g29); \ } #define define_ts_iiS_v(id, src_type) \ -static void ts_ ## id(int g28, int g29, Scheme_Object** g30) \ +static void ts_ ## id(int g30, int g31, Scheme_Object** g32) \ XFORM_SKIP_PROC \ { \ if (scheme_use_rtcall) \ - scheme_rtcall_iiS_v("[" #id "]", src_type, id, g28, g29, g30); \ + scheme_rtcall_iiS_v("[" #id "]", src_type, id, g30, g31, g32); \ else \ - id(g28, g29, g30); \ + id(g30, g31, g32); \ } #define define_ts_ss_v(id, src_type) \ -static void ts_ ## id(Scheme_Object* g31, Scheme_Object* g32) \ +static void ts_ ## id(Scheme_Object* g33, Scheme_Object* g34) \ XFORM_SKIP_PROC \ { \ if (scheme_use_rtcall) \ - scheme_rtcall_ss_v("[" #id "]", src_type, id, g31, g32); \ + scheme_rtcall_ss_v("[" #id "]", src_type, id, g33, g34); \ else \ - id(g31, g32); \ + id(g33, g34); \ } #define define_ts_b_v(id, src_type) \ -static void ts_ ## id(Scheme_Bucket* g33) \ +static void ts_ ## id(Scheme_Bucket* g35) \ XFORM_SKIP_PROC \ { \ if (scheme_use_rtcall) \ - scheme_rtcall_b_v("[" #id "]", src_type, id, g33); \ + scheme_rtcall_b_v("[" #id "]", src_type, id, g35); \ else \ - id(g33); \ + id(g35); \ } #define define_ts_sl_s(id, src_type) \ -static Scheme_Object* ts_ ## id(Scheme_Object* g34, intptr_t g35) \ +static Scheme_Object* ts_ ## id(Scheme_Object* g36, intptr_t g37) \ XFORM_SKIP_PROC \ { \ if (scheme_use_rtcall) \ - return scheme_rtcall_sl_s("[" #id "]", src_type, id, g34, g35); \ - else \ - return id(g34, g35); \ -} -#define define_ts_iS_s(id, src_type) \ -static Scheme_Object* ts_ ## id(int g36, Scheme_Object** g37) \ - XFORM_SKIP_PROC \ -{ \ - if (scheme_use_rtcall) \ - return scheme_rtcall_iS_s("[" #id "]", src_type, id, g36, g37); \ + return scheme_rtcall_sl_s("[" #id "]", src_type, id, g36, g37); \ else \ return id(g36, g37); \ } -#define define_ts_S_s(id, src_type) \ -static Scheme_Object* ts_ ## id(Scheme_Object** g38) \ +#define define_ts_iS_s(id, src_type) \ +static Scheme_Object* ts_ ## id(int g38, Scheme_Object** g39) \ XFORM_SKIP_PROC \ { \ if (scheme_use_rtcall) \ - return scheme_rtcall_S_s("[" #id "]", src_type, id, g38); \ + return scheme_rtcall_iS_s("[" #id "]", src_type, id, g38, g39); \ else \ - return id(g38); \ + return id(g38, g39); \ +} +#define define_ts_S_s(id, src_type) \ +static Scheme_Object* ts_ ## id(Scheme_Object** g40) \ + XFORM_SKIP_PROC \ +{ \ + if (scheme_use_rtcall) \ + return scheme_rtcall_S_s("[" #id "]", src_type, id, g40); \ + else \ + return id(g40); \ } #define define_ts_s_v(id, src_type) \ -static void ts_ ## id(Scheme_Object* g39) \ +static void ts_ ## id(Scheme_Object* g41) \ XFORM_SKIP_PROC \ { \ if (scheme_use_rtcall) \ - scheme_rtcall_s_v("[" #id "]", src_type, id, g39); \ + scheme_rtcall_s_v("[" #id "]", src_type, id, g41); \ else \ - id(g39); \ + id(g41); \ } #define define_ts_iSi_s(id, src_type) \ -static Scheme_Object* ts_ ## id(int g40, Scheme_Object** g41, int g42) \ +static Scheme_Object* ts_ ## id(int g42, Scheme_Object** g43, int g44) \ XFORM_SKIP_PROC \ { \ if (scheme_use_rtcall) \ - return scheme_rtcall_iSi_s("[" #id "]", src_type, id, g40, g41, g42); \ + return scheme_rtcall_iSi_s("[" #id "]", src_type, id, g42, g43, g44); \ else \ - return id(g40, g41, g42); \ + return id(g42, g43, g44); \ } #define define_ts_siS_v(id, src_type) \ -static void ts_ ## id(Scheme_Object* g43, int g44, Scheme_Object** g45) \ +static void ts_ ## id(Scheme_Object* g45, int g46, Scheme_Object** g47) \ XFORM_SKIP_PROC \ { \ if (scheme_use_rtcall) \ - scheme_rtcall_siS_v("[" #id "]", src_type, id, g43, g44, g45); \ + scheme_rtcall_siS_v("[" #id "]", src_type, id, g45, g46, g47); \ else \ - id(g43, g44, g45); \ + id(g45, g46, g47); \ } #define define_ts_z_p(id, src_type) \ -static void* ts_ ## id(size_t g46) \ +static void* ts_ ## id(size_t g48) \ XFORM_SKIP_PROC \ { \ if (scheme_use_rtcall) \ - return scheme_rtcall_z_p("[" #id "]", src_type, id, g46); \ + return scheme_rtcall_z_p("[" #id "]", src_type, id, g48); \ else \ - return id(g46); \ + return id(g48); \ } #define define_ts_si_s(id, src_type) \ -static Scheme_Object* ts_ ## id(Scheme_Object* g47, int g48) \ +static Scheme_Object* ts_ ## id(Scheme_Object* g49, int g50) \ XFORM_SKIP_PROC \ { \ if (scheme_use_rtcall) \ - return scheme_rtcall_si_s("[" #id "]", src_type, id, g47, g48); \ + return scheme_rtcall_si_s("[" #id "]", src_type, id, g49, g50); \ else \ - return id(g47, g48); \ + return id(g49, g50); \ } #define define_ts_sis_v(id, src_type) \ -static void ts_ ## id(Scheme_Object* g49, int g50, Scheme_Object* g51) \ +static void ts_ ## id(Scheme_Object* g51, int g52, Scheme_Object* g53) \ XFORM_SKIP_PROC \ { \ if (scheme_use_rtcall) \ - scheme_rtcall_sis_v("[" #id "]", src_type, id, g49, g50, g51); \ + scheme_rtcall_sis_v("[" #id "]", src_type, id, g51, g52, g53); \ else \ - id(g49, g50, g51); \ + id(g51, g52, g53); \ } #define define_ts_ss_i(id, src_type) \ -static int ts_ ## id(Scheme_Object* g52, Scheme_Object* g53) \ +static int ts_ ## id(Scheme_Object* g54, Scheme_Object* g55) \ XFORM_SKIP_PROC \ { \ if (scheme_use_rtcall) \ - return scheme_rtcall_ss_i("[" #id "]", src_type, id, g52, g53); \ + return scheme_rtcall_ss_i("[" #id "]", src_type, id, g54, g55); \ else \ - return id(g52, g53); \ + return id(g54, g55); \ } #define define_ts_iSp_v(id, src_type) \ -static void ts_ ## id(int g54, Scheme_Object** g55, void* g56) \ +static void ts_ ## id(int g56, Scheme_Object** g57, void* g58) \ XFORM_SKIP_PROC \ { \ if (scheme_use_rtcall) \ - scheme_rtcall_iSp_v("[" #id "]", src_type, id, g54, g55, g56); \ + scheme_rtcall_iSp_v("[" #id "]", src_type, id, g56, g57, g58); \ else \ - id(g54, g55, g56); \ + id(g56, g57, g58); \ } #define define_ts_sss_s(id, src_type) \ -static Scheme_Object* ts_ ## id(Scheme_Object* g57, Scheme_Object* g58, Scheme_Object* g59) \ +static Scheme_Object* ts_ ## id(Scheme_Object* g59, Scheme_Object* g60, Scheme_Object* g61) \ XFORM_SKIP_PROC \ { \ if (scheme_use_rtcall) \ - return scheme_rtcall_sss_s("[" #id "]", src_type, id, g57, g58, g59); \ + return scheme_rtcall_sss_s("[" #id "]", src_type, id, g59, g60, g61); \ else \ - return id(g57, g58, g59); \ + return id(g59, g60, g61); \ } diff --git a/src/racket/src/jit_ts_future_glue.c b/src/racket/src/jit_ts_future_glue.c index 0512891562..706db8b8b3 100644 --- a/src/racket/src/jit_ts_future_glue.c +++ b/src/racket/src/jit_ts_future_glue.c @@ -1,4 +1,4 @@ - Scheme_Object* scheme_rtcall_siS_s(const char *who, int src_type, prim_siS_s f, Scheme_Object* g60, int g61, Scheme_Object** g62) + Scheme_Object* scheme_rtcall_siS_s(const char *who, int src_type, prim_siS_s f, Scheme_Object* g62, int g63, Scheme_Object** g64) XFORM_SKIP_PROC { Scheme_Future_Thread_State *fts = scheme_future_thread_state; @@ -13,11 +13,11 @@ future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; - future->arg_s0 = g60; - future->arg_i1 = g61; - future->arg_S2 = g62; + future->arg_s0 = g62; + future->arg_i1 = g63; + future->arg_S2 = g64; - future_do_runtimecall(fts, (void*)f, 0, 1); + future_do_runtimecall(fts, (void*)f, 0, 1, 0); fts->thread = scheme_current_thread; future = fts->thread->current_ft; retval = future->retval_s; @@ -25,7 +25,7 @@ receive_special_result(future, retval, 1); return retval; } - Scheme_Object* scheme_rtcall_iSs_s(const char *who, int src_type, prim_iSs_s f, int g63, Scheme_Object** g64, Scheme_Object* g65) + Scheme_Object* scheme_rtcall_iSs_s(const char *who, int src_type, prim_iSs_s f, int g65, Scheme_Object** g66, Scheme_Object* g67) XFORM_SKIP_PROC { Scheme_Future_Thread_State *fts = scheme_future_thread_state; @@ -40,11 +40,11 @@ future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; - future->arg_i0 = g63; - future->arg_S1 = g64; - future->arg_s2 = g65; + future->arg_i0 = g65; + future->arg_S1 = g66; + future->arg_s2 = g67; - future_do_runtimecall(fts, (void*)f, 0, 1); + future_do_runtimecall(fts, (void*)f, 0, 1, 0); fts->thread = scheme_current_thread; future = fts->thread->current_ft; retval = future->retval_s; @@ -52,7 +52,7 @@ receive_special_result(future, retval, 1); return retval; } - Scheme_Object* scheme_rtcall_s_s(const char *who, int src_type, prim_s_s f, Scheme_Object* g66) + Scheme_Object* scheme_rtcall_s_s(const char *who, int src_type, prim_s_s f, Scheme_Object* g68) XFORM_SKIP_PROC { Scheme_Future_Thread_State *fts = scheme_future_thread_state; @@ -67,9 +67,9 @@ future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; - future->arg_s0 = g66; - send_special_result(future, g66); - future_do_runtimecall(fts, (void*)f, 0, 1); + future->arg_s0 = g68; + send_special_result(future, g68); + future_do_runtimecall(fts, (void*)f, 0, 1, 0); fts->thread = scheme_current_thread; future = fts->thread->current_ft; retval = future->retval_s; @@ -77,7 +77,7 @@ receive_special_result(future, retval, 1); return retval; } - Scheme_Object* scheme_rtcall_n_s(const char *who, int src_type, prim_n_s f, Scheme_Native_Closure_Data* g67) + Scheme_Object* scheme_rtcall_n_s(const char *who, int src_type, prim_n_s f, Scheme_Native_Closure_Data* g69) XFORM_SKIP_PROC { Scheme_Future_Thread_State *fts = scheme_future_thread_state; @@ -92,9 +92,9 @@ future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; - future->arg_n0 = g67; + future->arg_n0 = g69; - future_do_runtimecall(fts, (void*)f, 0, 1); + future_do_runtimecall(fts, (void*)f, 0, 1, 0); fts->thread = scheme_current_thread; future = fts->thread->current_ft; retval = future->retval_s; @@ -119,7 +119,7 @@ future->source_type = src_type; - future_do_runtimecall(fts, (void*)f, 0, 1); + future_do_runtimecall(fts, (void*)f, 0, 1, 0); fts->thread = scheme_current_thread; future = fts->thread->current_ft; retval = future->retval_s; @@ -127,7 +127,7 @@ receive_special_result(future, retval, 1); return retval; } - Scheme_Object* scheme_rtcall_ss_s(const char *who, int src_type, prim_ss_s f, Scheme_Object* g68, Scheme_Object* g69) + Scheme_Object* scheme_rtcall_ss_s(const char *who, int src_type, prim_ss_s f, Scheme_Object* g70, Scheme_Object* g71) XFORM_SKIP_PROC { Scheme_Future_Thread_State *fts = scheme_future_thread_state; @@ -142,10 +142,10 @@ future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; - future->arg_s0 = g68; - future->arg_s1 = g69; + future->arg_s0 = g70; + future->arg_s1 = g71; - future_do_runtimecall(fts, (void*)f, 0, 1); + future_do_runtimecall(fts, (void*)f, 0, 1, 0); fts->thread = scheme_current_thread; future = fts->thread->current_ft; retval = future->retval_s; @@ -153,7 +153,7 @@ receive_special_result(future, retval, 1); return retval; } - Scheme_Object* scheme_rtcall_ssi_s(const char *who, int src_type, prim_ssi_s f, Scheme_Object* g70, Scheme_Object* g71, int g72) + Scheme_Object* scheme_rtcall_ssi_s(const char *who, int src_type, prim_ssi_s f, Scheme_Object* g72, Scheme_Object* g73, int g74) XFORM_SKIP_PROC { Scheme_Future_Thread_State *fts = scheme_future_thread_state; @@ -168,11 +168,11 @@ future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; - future->arg_s0 = g70; - future->arg_s1 = g71; - future->arg_i2 = g72; + future->arg_s0 = g72; + future->arg_s1 = g73; + future->arg_i2 = g74; - future_do_runtimecall(fts, (void*)f, 0, 1); + future_do_runtimecall(fts, (void*)f, 0, 1, 0); fts->thread = scheme_current_thread; future = fts->thread->current_ft; retval = future->retval_s; @@ -180,7 +180,7 @@ receive_special_result(future, retval, 1); return retval; } - Scheme_Object* scheme_rtcall_tt_s(const char *who, int src_type, prim_tt_s f, const Scheme_Object* g73, const Scheme_Object* g74) + Scheme_Object* scheme_rtcall_tt_s(const char *who, int src_type, prim_tt_s f, const Scheme_Object* g75, const Scheme_Object* g76) XFORM_SKIP_PROC { Scheme_Future_Thread_State *fts = scheme_future_thread_state; @@ -195,10 +195,10 @@ future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; - future->arg_t0 = g73; - future->arg_t1 = g74; + future->arg_t0 = g75; + future->arg_t1 = g76; - future_do_runtimecall(fts, (void*)f, 0, 1); + future_do_runtimecall(fts, (void*)f, 0, 1, 0); fts->thread = scheme_current_thread; future = fts->thread->current_ft; retval = future->retval_s; @@ -206,7 +206,7 @@ receive_special_result(future, retval, 1); return retval; } - MZ_MARK_STACK_TYPE scheme_rtcall_ss_m(const char *who, int src_type, prim_ss_m f, Scheme_Object* g75, Scheme_Object* g76) + MZ_MARK_STACK_TYPE scheme_rtcall_ss_m(const char *who, int src_type, prim_ss_m f, Scheme_Object* g77, Scheme_Object* g78) XFORM_SKIP_PROC { Scheme_Future_Thread_State *fts = scheme_future_thread_state; @@ -221,10 +221,10 @@ future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; - future->arg_s0 = g75; - future->arg_s1 = g76; + future->arg_s0 = g77; + future->arg_s1 = g78; - future_do_runtimecall(fts, (void*)f, 0, 1); + future_do_runtimecall(fts, (void*)f, 0, 1, 0); fts->thread = scheme_current_thread; future = fts->thread->current_ft; retval = future->retval_m; @@ -232,7 +232,7 @@ return retval; } - Scheme_Object* scheme_rtcall_Sl_s(const char *who, int src_type, prim_Sl_s f, Scheme_Object** g77, intptr_t g78) + Scheme_Object* scheme_rtcall_Sl_s(const char *who, int src_type, prim_Sl_s f, Scheme_Object** g79, intptr_t g80) XFORM_SKIP_PROC { Scheme_Future_Thread_State *fts = scheme_future_thread_state; @@ -247,10 +247,10 @@ future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; - future->arg_S0 = g77; - future->arg_l1 = g78; + future->arg_S0 = g79; + future->arg_l1 = g80; - future_do_runtimecall(fts, (void*)f, 0, 1); + future_do_runtimecall(fts, (void*)f, 0, 1, 0); fts->thread = scheme_current_thread; future = fts->thread->current_ft; retval = future->retval_s; @@ -258,7 +258,7 @@ receive_special_result(future, retval, 1); return retval; } - Scheme_Object* scheme_rtcall_l_s(const char *who, int src_type, prim_l_s f, intptr_t g79) + Scheme_Object* scheme_rtcall_l_s(const char *who, int src_type, prim_l_s f, intptr_t g81) XFORM_SKIP_PROC { Scheme_Future_Thread_State *fts = scheme_future_thread_state; @@ -273,9 +273,9 @@ future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; - future->arg_l0 = g79; + future->arg_l0 = g81; - future_do_runtimecall(fts, (void*)f, 0, 1); + future_do_runtimecall(fts, (void*)f, 0, 1, 0); fts->thread = scheme_current_thread; future = fts->thread->current_ft; retval = future->retval_s; @@ -283,7 +283,7 @@ receive_special_result(future, retval, 1); return retval; } - void scheme_rtcall_bsi_v(const char *who, int src_type, prim_bsi_v f, Scheme_Bucket* g80, Scheme_Object* g81, int g82) + void scheme_rtcall_bsi_v(const char *who, int src_type, prim_bsi_v f, Scheme_Bucket* g82, Scheme_Object* g83, int g84) XFORM_SKIP_PROC { Scheme_Future_Thread_State *fts = scheme_future_thread_state; @@ -298,11 +298,11 @@ future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; - future->arg_b0 = g80; - future->arg_s1 = g81; - future->arg_i2 = g82; + future->arg_b0 = g82; + future->arg_s1 = g83; + future->arg_i2 = g84; - future_do_runtimecall(fts, (void*)f, 0, 1); + future_do_runtimecall(fts, (void*)f, 0, 1, 0); fts->thread = scheme_current_thread; future = fts->thread->current_ft; @@ -310,7 +310,7 @@ } - void scheme_rtcall_iiS_v(const char *who, int src_type, prim_iiS_v f, int g83, int g84, Scheme_Object** g85) + void scheme_rtcall_iiS_v(const char *who, int src_type, prim_iiS_v f, int g85, int g86, Scheme_Object** g87) XFORM_SKIP_PROC { Scheme_Future_Thread_State *fts = scheme_future_thread_state; @@ -325,11 +325,11 @@ future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; - future->arg_i0 = g83; - future->arg_i1 = g84; - future->arg_S2 = g85; + future->arg_i0 = g85; + future->arg_i1 = g86; + future->arg_S2 = g87; - future_do_runtimecall(fts, (void*)f, 0, 1); + future_do_runtimecall(fts, (void*)f, 0, 1, 0); fts->thread = scheme_current_thread; future = fts->thread->current_ft; @@ -337,7 +337,7 @@ } - void scheme_rtcall_ss_v(const char *who, int src_type, prim_ss_v f, Scheme_Object* g86, Scheme_Object* g87) + void scheme_rtcall_ss_v(const char *who, int src_type, prim_ss_v f, Scheme_Object* g88, Scheme_Object* g89) XFORM_SKIP_PROC { Scheme_Future_Thread_State *fts = scheme_future_thread_state; @@ -352,10 +352,10 @@ future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; - future->arg_s0 = g86; - future->arg_s1 = g87; + future->arg_s0 = g88; + future->arg_s1 = g89; - future_do_runtimecall(fts, (void*)f, 0, 1); + future_do_runtimecall(fts, (void*)f, 0, 1, 0); fts->thread = scheme_current_thread; future = fts->thread->current_ft; @@ -363,7 +363,7 @@ } - void scheme_rtcall_b_v(const char *who, int src_type, prim_b_v f, Scheme_Bucket* g88) + void scheme_rtcall_b_v(const char *who, int src_type, prim_b_v f, Scheme_Bucket* g90) XFORM_SKIP_PROC { Scheme_Future_Thread_State *fts = scheme_future_thread_state; @@ -378,9 +378,9 @@ future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; - future->arg_b0 = g88; + future->arg_b0 = g90; - future_do_runtimecall(fts, (void*)f, 0, 1); + future_do_runtimecall(fts, (void*)f, 0, 1, 0); fts->thread = scheme_current_thread; future = fts->thread->current_ft; @@ -388,7 +388,7 @@ } - Scheme_Object* scheme_rtcall_sl_s(const char *who, int src_type, prim_sl_s f, Scheme_Object* g89, intptr_t g90) + Scheme_Object* scheme_rtcall_sl_s(const char *who, int src_type, prim_sl_s f, Scheme_Object* g91, intptr_t g92) XFORM_SKIP_PROC { Scheme_Future_Thread_State *fts = scheme_future_thread_state; @@ -403,10 +403,10 @@ future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; - future->arg_s0 = g89; - future->arg_l1 = g90; + future->arg_s0 = g91; + future->arg_l1 = g92; - future_do_runtimecall(fts, (void*)f, 0, 1); + future_do_runtimecall(fts, (void*)f, 0, 1, 0); fts->thread = scheme_current_thread; future = fts->thread->current_ft; retval = future->retval_s; @@ -414,7 +414,7 @@ receive_special_result(future, retval, 1); return retval; } - Scheme_Object* scheme_rtcall_iS_s(const char *who, int src_type, prim_iS_s f, int g91, Scheme_Object** g92) + Scheme_Object* scheme_rtcall_iS_s(const char *who, int src_type, prim_iS_s f, int g93, Scheme_Object** g94) XFORM_SKIP_PROC { Scheme_Future_Thread_State *fts = scheme_future_thread_state; @@ -429,10 +429,10 @@ future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; - future->arg_i0 = g91; - future->arg_S1 = g92; + future->arg_i0 = g93; + future->arg_S1 = g94; - future_do_runtimecall(fts, (void*)f, 0, 1); + future_do_runtimecall(fts, (void*)f, 0, 1, 0); fts->thread = scheme_current_thread; future = fts->thread->current_ft; retval = future->retval_s; @@ -440,7 +440,7 @@ receive_special_result(future, retval, 1); return retval; } - Scheme_Object* scheme_rtcall_S_s(const char *who, int src_type, prim_S_s f, Scheme_Object** g93) + Scheme_Object* scheme_rtcall_S_s(const char *who, int src_type, prim_S_s f, Scheme_Object** g95) XFORM_SKIP_PROC { Scheme_Future_Thread_State *fts = scheme_future_thread_state; @@ -455,9 +455,9 @@ future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; - future->arg_S0 = g93; + future->arg_S0 = g95; - future_do_runtimecall(fts, (void*)f, 0, 1); + future_do_runtimecall(fts, (void*)f, 0, 1, 0); fts->thread = scheme_current_thread; future = fts->thread->current_ft; retval = future->retval_s; @@ -465,7 +465,7 @@ receive_special_result(future, retval, 1); return retval; } - void scheme_rtcall_s_v(const char *who, int src_type, prim_s_v f, Scheme_Object* g94) + void scheme_rtcall_s_v(const char *who, int src_type, prim_s_v f, Scheme_Object* g96) XFORM_SKIP_PROC { Scheme_Future_Thread_State *fts = scheme_future_thread_state; @@ -480,9 +480,9 @@ future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; - future->arg_s0 = g94; - send_special_result(future, g94); - future_do_runtimecall(fts, (void*)f, 0, 1); + future->arg_s0 = g96; + send_special_result(future, g96); + future_do_runtimecall(fts, (void*)f, 0, 1, 0); fts->thread = scheme_current_thread; future = fts->thread->current_ft; @@ -490,7 +490,7 @@ } - Scheme_Object* scheme_rtcall_iSi_s(const char *who, int src_type, prim_iSi_s f, int g95, Scheme_Object** g96, int g97) + Scheme_Object* scheme_rtcall_iSi_s(const char *who, int src_type, prim_iSi_s f, int g97, Scheme_Object** g98, int g99) XFORM_SKIP_PROC { Scheme_Future_Thread_State *fts = scheme_future_thread_state; @@ -505,11 +505,11 @@ future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; - future->arg_i0 = g95; - future->arg_S1 = g96; - future->arg_i2 = g97; + future->arg_i0 = g97; + future->arg_S1 = g98; + future->arg_i2 = g99; - future_do_runtimecall(fts, (void*)f, 0, 1); + future_do_runtimecall(fts, (void*)f, 0, 1, 0); fts->thread = scheme_current_thread; future = fts->thread->current_ft; retval = future->retval_s; @@ -517,7 +517,7 @@ receive_special_result(future, retval, 1); return retval; } - void scheme_rtcall_siS_v(const char *who, int src_type, prim_siS_v f, Scheme_Object* g98, int g99, Scheme_Object** g100) + void scheme_rtcall_siS_v(const char *who, int src_type, prim_siS_v f, Scheme_Object* g100, int g101, Scheme_Object** g102) XFORM_SKIP_PROC { Scheme_Future_Thread_State *fts = scheme_future_thread_state; @@ -532,11 +532,11 @@ future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; - future->arg_s0 = g98; - future->arg_i1 = g99; - future->arg_S2 = g100; + future->arg_s0 = g100; + future->arg_i1 = g101; + future->arg_S2 = g102; - future_do_runtimecall(fts, (void*)f, 0, 1); + future_do_runtimecall(fts, (void*)f, 0, 1, 0); fts->thread = scheme_current_thread; future = fts->thread->current_ft; @@ -544,7 +544,7 @@ } - void* scheme_rtcall_z_p(const char *who, int src_type, prim_z_p f, size_t g101) + void* scheme_rtcall_z_p(const char *who, int src_type, prim_z_p f, size_t g103) XFORM_SKIP_PROC { Scheme_Future_Thread_State *fts = scheme_future_thread_state; @@ -559,9 +559,9 @@ future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; - future->arg_z0 = g101; + future->arg_z0 = g103; - future_do_runtimecall(fts, (void*)f, 0, 1); + future_do_runtimecall(fts, (void*)f, 0, 1, 0); fts->thread = scheme_current_thread; future = fts->thread->current_ft; retval = future->retval_p; @@ -569,7 +569,7 @@ return retval; } - Scheme_Object* scheme_rtcall_si_s(const char *who, int src_type, prim_si_s f, Scheme_Object* g102, int g103) + Scheme_Object* scheme_rtcall_si_s(const char *who, int src_type, prim_si_s f, Scheme_Object* g104, int g105) XFORM_SKIP_PROC { Scheme_Future_Thread_State *fts = scheme_future_thread_state; @@ -584,10 +584,10 @@ future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; - future->arg_s0 = g102; - future->arg_i1 = g103; + future->arg_s0 = g104; + future->arg_i1 = g105; - future_do_runtimecall(fts, (void*)f, 0, 1); + future_do_runtimecall(fts, (void*)f, 0, 1, 0); fts->thread = scheme_current_thread; future = fts->thread->current_ft; retval = future->retval_s; @@ -595,7 +595,7 @@ receive_special_result(future, retval, 1); return retval; } - void scheme_rtcall_sis_v(const char *who, int src_type, prim_sis_v f, Scheme_Object* g104, int g105, Scheme_Object* g106) + void scheme_rtcall_sis_v(const char *who, int src_type, prim_sis_v f, Scheme_Object* g106, int g107, Scheme_Object* g108) XFORM_SKIP_PROC { Scheme_Future_Thread_State *fts = scheme_future_thread_state; @@ -610,11 +610,11 @@ future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; - future->arg_s0 = g104; - future->arg_i1 = g105; - future->arg_s2 = g106; + future->arg_s0 = g106; + future->arg_i1 = g107; + future->arg_s2 = g108; - future_do_runtimecall(fts, (void*)f, 0, 1); + future_do_runtimecall(fts, (void*)f, 0, 1, 0); fts->thread = scheme_current_thread; future = fts->thread->current_ft; @@ -622,7 +622,7 @@ } - int scheme_rtcall_ss_i(const char *who, int src_type, prim_ss_i f, Scheme_Object* g107, Scheme_Object* g108) + int scheme_rtcall_ss_i(const char *who, int src_type, prim_ss_i f, Scheme_Object* g109, Scheme_Object* g110) XFORM_SKIP_PROC { Scheme_Future_Thread_State *fts = scheme_future_thread_state; @@ -637,10 +637,10 @@ future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; - future->arg_s0 = g107; - future->arg_s1 = g108; + future->arg_s0 = g109; + future->arg_s1 = g110; - future_do_runtimecall(fts, (void*)f, 0, 1); + future_do_runtimecall(fts, (void*)f, 0, 1, 0); fts->thread = scheme_current_thread; future = fts->thread->current_ft; retval = future->retval_i; @@ -648,7 +648,7 @@ return retval; } - void scheme_rtcall_iSp_v(const char *who, int src_type, prim_iSp_v f, int g109, Scheme_Object** g110, void* g111) + void scheme_rtcall_iSp_v(const char *who, int src_type, prim_iSp_v f, int g111, Scheme_Object** g112, void* g113) XFORM_SKIP_PROC { Scheme_Future_Thread_State *fts = scheme_future_thread_state; @@ -663,11 +663,11 @@ future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; - future->arg_i0 = g109; - future->arg_S1 = g110; - future->arg_p2 = g111; + future->arg_i0 = g111; + future->arg_S1 = g112; + future->arg_p2 = g113; - future_do_runtimecall(fts, (void*)f, 0, 1); + future_do_runtimecall(fts, (void*)f, 0, 1, 0); fts->thread = scheme_current_thread; future = fts->thread->current_ft; @@ -675,7 +675,7 @@ } - Scheme_Object* scheme_rtcall_sss_s(const char *who, int src_type, prim_sss_s f, Scheme_Object* g112, Scheme_Object* g113, Scheme_Object* g114) + Scheme_Object* scheme_rtcall_sss_s(const char *who, int src_type, prim_sss_s f, Scheme_Object* g114, Scheme_Object* g115, Scheme_Object* g116) XFORM_SKIP_PROC { Scheme_Future_Thread_State *fts = scheme_future_thread_state; @@ -690,11 +690,11 @@ future->time_of_request = tm; future->source_of_request = who; future->source_type = src_type; - future->arg_s0 = g112; - future->arg_s1 = g113; - future->arg_s2 = g114; + future->arg_s0 = g114; + future->arg_s1 = g115; + future->arg_s2 = g116; - future_do_runtimecall(fts, (void*)f, 0, 1); + future_do_runtimecall(fts, (void*)f, 0, 1, 0); fts->thread = scheme_current_thread; future = fts->thread->current_ft; retval = future->retval_s; diff --git a/src/racket/src/jit_ts_protos.h b/src/racket/src/jit_ts_protos.h index cfcc000324..c81beac67f 100644 --- a/src/racket/src/jit_ts_protos.h +++ b/src/racket/src/jit_ts_protos.h @@ -1,81 +1,81 @@ #define SIG_siS_s 10 typedef Scheme_Object* (*prim_siS_s)(Scheme_Object*, int, Scheme_Object**); -Scheme_Object* scheme_rtcall_siS_s(const char *who, int src_type, prim_siS_s f, Scheme_Object* g170, int g171, Scheme_Object** g172); +Scheme_Object* scheme_rtcall_siS_s(const char *who, int src_type, prim_siS_s f, Scheme_Object* g172, int g173, Scheme_Object** g174); #define SIG_iSs_s 11 typedef Scheme_Object* (*prim_iSs_s)(int, Scheme_Object**, Scheme_Object*); -Scheme_Object* scheme_rtcall_iSs_s(const char *who, int src_type, prim_iSs_s f, int g173, Scheme_Object** g174, Scheme_Object* g175); +Scheme_Object* scheme_rtcall_iSs_s(const char *who, int src_type, prim_iSs_s f, int g175, Scheme_Object** g176, Scheme_Object* g177); #define SIG_s_s 12 typedef Scheme_Object* (*prim_s_s)(Scheme_Object*); -Scheme_Object* scheme_rtcall_s_s(const char *who, int src_type, prim_s_s f, Scheme_Object* g176); +Scheme_Object* scheme_rtcall_s_s(const char *who, int src_type, prim_s_s f, Scheme_Object* g178); #define SIG_n_s 13 typedef Scheme_Object* (*prim_n_s)(Scheme_Native_Closure_Data*); -Scheme_Object* scheme_rtcall_n_s(const char *who, int src_type, prim_n_s f, Scheme_Native_Closure_Data* g177); +Scheme_Object* scheme_rtcall_n_s(const char *who, int src_type, prim_n_s f, Scheme_Native_Closure_Data* g179); #define SIG__s 14 typedef Scheme_Object* (*prim__s)(); Scheme_Object* scheme_rtcall__s(const char *who, int src_type, prim__s f ); #define SIG_ss_s 15 typedef Scheme_Object* (*prim_ss_s)(Scheme_Object*, Scheme_Object*); -Scheme_Object* scheme_rtcall_ss_s(const char *who, int src_type, prim_ss_s f, Scheme_Object* g178, Scheme_Object* g179); +Scheme_Object* scheme_rtcall_ss_s(const char *who, int src_type, prim_ss_s f, Scheme_Object* g180, Scheme_Object* g181); #define SIG_ssi_s 16 typedef Scheme_Object* (*prim_ssi_s)(Scheme_Object*, Scheme_Object*, int); -Scheme_Object* scheme_rtcall_ssi_s(const char *who, int src_type, prim_ssi_s f, Scheme_Object* g180, Scheme_Object* g181, int g182); +Scheme_Object* scheme_rtcall_ssi_s(const char *who, int src_type, prim_ssi_s f, Scheme_Object* g182, Scheme_Object* g183, int g184); #define SIG_tt_s 17 typedef Scheme_Object* (*prim_tt_s)(const Scheme_Object*, const Scheme_Object*); -Scheme_Object* scheme_rtcall_tt_s(const char *who, int src_type, prim_tt_s f, const Scheme_Object* g183, const Scheme_Object* g184); +Scheme_Object* scheme_rtcall_tt_s(const char *who, int src_type, prim_tt_s f, const Scheme_Object* g185, const Scheme_Object* g186); #define SIG_ss_m 18 typedef MZ_MARK_STACK_TYPE (*prim_ss_m)(Scheme_Object*, Scheme_Object*); -MZ_MARK_STACK_TYPE scheme_rtcall_ss_m(const char *who, int src_type, prim_ss_m f, Scheme_Object* g185, Scheme_Object* g186); +MZ_MARK_STACK_TYPE scheme_rtcall_ss_m(const char *who, int src_type, prim_ss_m f, Scheme_Object* g187, Scheme_Object* g188); #define SIG_Sl_s 19 typedef Scheme_Object* (*prim_Sl_s)(Scheme_Object**, intptr_t); -Scheme_Object* scheme_rtcall_Sl_s(const char *who, int src_type, prim_Sl_s f, Scheme_Object** g187, intptr_t g188); +Scheme_Object* scheme_rtcall_Sl_s(const char *who, int src_type, prim_Sl_s f, Scheme_Object** g189, intptr_t g190); #define SIG_l_s 20 typedef Scheme_Object* (*prim_l_s)(intptr_t); -Scheme_Object* scheme_rtcall_l_s(const char *who, int src_type, prim_l_s f, intptr_t g189); +Scheme_Object* scheme_rtcall_l_s(const char *who, int src_type, prim_l_s f, intptr_t g191); #define SIG_bsi_v 21 typedef void (*prim_bsi_v)(Scheme_Bucket*, Scheme_Object*, int); -void scheme_rtcall_bsi_v(const char *who, int src_type, prim_bsi_v f, Scheme_Bucket* g190, Scheme_Object* g191, int g192); +void scheme_rtcall_bsi_v(const char *who, int src_type, prim_bsi_v f, Scheme_Bucket* g192, Scheme_Object* g193, int g194); #define SIG_iiS_v 22 typedef void (*prim_iiS_v)(int, int, Scheme_Object**); -void scheme_rtcall_iiS_v(const char *who, int src_type, prim_iiS_v f, int g193, int g194, Scheme_Object** g195); +void scheme_rtcall_iiS_v(const char *who, int src_type, prim_iiS_v f, int g195, int g196, Scheme_Object** g197); #define SIG_ss_v 23 typedef void (*prim_ss_v)(Scheme_Object*, Scheme_Object*); -void scheme_rtcall_ss_v(const char *who, int src_type, prim_ss_v f, Scheme_Object* g196, Scheme_Object* g197); +void scheme_rtcall_ss_v(const char *who, int src_type, prim_ss_v f, Scheme_Object* g198, Scheme_Object* g199); #define SIG_b_v 24 typedef void (*prim_b_v)(Scheme_Bucket*); -void scheme_rtcall_b_v(const char *who, int src_type, prim_b_v f, Scheme_Bucket* g198); +void scheme_rtcall_b_v(const char *who, int src_type, prim_b_v f, Scheme_Bucket* g200); #define SIG_sl_s 25 typedef Scheme_Object* (*prim_sl_s)(Scheme_Object*, intptr_t); -Scheme_Object* scheme_rtcall_sl_s(const char *who, int src_type, prim_sl_s f, Scheme_Object* g199, intptr_t g200); +Scheme_Object* scheme_rtcall_sl_s(const char *who, int src_type, prim_sl_s f, Scheme_Object* g201, intptr_t g202); #define SIG_iS_s 26 typedef Scheme_Object* (*prim_iS_s)(int, Scheme_Object**); -Scheme_Object* scheme_rtcall_iS_s(const char *who, int src_type, prim_iS_s f, int g201, Scheme_Object** g202); +Scheme_Object* scheme_rtcall_iS_s(const char *who, int src_type, prim_iS_s f, int g203, Scheme_Object** g204); #define SIG_S_s 27 typedef Scheme_Object* (*prim_S_s)(Scheme_Object**); -Scheme_Object* scheme_rtcall_S_s(const char *who, int src_type, prim_S_s f, Scheme_Object** g203); +Scheme_Object* scheme_rtcall_S_s(const char *who, int src_type, prim_S_s f, Scheme_Object** g205); #define SIG_s_v 28 typedef void (*prim_s_v)(Scheme_Object*); -void scheme_rtcall_s_v(const char *who, int src_type, prim_s_v f, Scheme_Object* g204); +void scheme_rtcall_s_v(const char *who, int src_type, prim_s_v f, Scheme_Object* g206); #define SIG_iSi_s 29 typedef Scheme_Object* (*prim_iSi_s)(int, Scheme_Object**, int); -Scheme_Object* scheme_rtcall_iSi_s(const char *who, int src_type, prim_iSi_s f, int g205, Scheme_Object** g206, int g207); +Scheme_Object* scheme_rtcall_iSi_s(const char *who, int src_type, prim_iSi_s f, int g207, Scheme_Object** g208, int g209); #define SIG_siS_v 30 typedef void (*prim_siS_v)(Scheme_Object*, int, Scheme_Object**); -void scheme_rtcall_siS_v(const char *who, int src_type, prim_siS_v f, Scheme_Object* g208, int g209, Scheme_Object** g210); +void scheme_rtcall_siS_v(const char *who, int src_type, prim_siS_v f, Scheme_Object* g210, int g211, Scheme_Object** g212); #define SIG_z_p 31 typedef void* (*prim_z_p)(size_t); -void* scheme_rtcall_z_p(const char *who, int src_type, prim_z_p f, size_t g211); +void* scheme_rtcall_z_p(const char *who, int src_type, prim_z_p f, size_t g213); #define SIG_si_s 32 typedef Scheme_Object* (*prim_si_s)(Scheme_Object*, int); -Scheme_Object* scheme_rtcall_si_s(const char *who, int src_type, prim_si_s f, Scheme_Object* g212, int g213); +Scheme_Object* scheme_rtcall_si_s(const char *who, int src_type, prim_si_s f, Scheme_Object* g214, int g215); #define SIG_sis_v 33 typedef void (*prim_sis_v)(Scheme_Object*, int, Scheme_Object*); -void scheme_rtcall_sis_v(const char *who, int src_type, prim_sis_v f, Scheme_Object* g214, int g215, Scheme_Object* g216); +void scheme_rtcall_sis_v(const char *who, int src_type, prim_sis_v f, Scheme_Object* g216, int g217, Scheme_Object* g218); #define SIG_ss_i 34 typedef int (*prim_ss_i)(Scheme_Object*, Scheme_Object*); -int scheme_rtcall_ss_i(const char *who, int src_type, prim_ss_i f, Scheme_Object* g217, Scheme_Object* g218); +int scheme_rtcall_ss_i(const char *who, int src_type, prim_ss_i f, Scheme_Object* g219, Scheme_Object* g220); #define SIG_iSp_v 35 typedef void (*prim_iSp_v)(int, Scheme_Object**, void*); -void scheme_rtcall_iSp_v(const char *who, int src_type, prim_iSp_v f, int g219, Scheme_Object** g220, void* g221); +void scheme_rtcall_iSp_v(const char *who, int src_type, prim_iSp_v f, int g221, Scheme_Object** g222, void* g223); #define SIG_sss_s 36 typedef Scheme_Object* (*prim_sss_s)(Scheme_Object*, Scheme_Object*, Scheme_Object*); -Scheme_Object* scheme_rtcall_sss_s(const char *who, int src_type, prim_sss_s f, Scheme_Object* g222, Scheme_Object* g223, Scheme_Object* g224); +Scheme_Object* scheme_rtcall_sss_s(const char *who, int src_type, prim_sss_s f, Scheme_Object* g224, Scheme_Object* g225, Scheme_Object* g226); diff --git a/src/racket/src/jitcall.c b/src/racket/src/jitcall.c index 581eaf3756..80af1d953f 100644 --- a/src/racket/src/jitcall.c +++ b/src/racket/src/jitcall.c @@ -199,6 +199,45 @@ static Scheme_Object *_scheme_tail_apply_from_native_fixup_args(Scheme_Object *r return ts__scheme_tail_apply_from_native(rator, argc + already, base); } +#if defined(MZ_USE_FUTURES) && defined(MZ_PRECISE_GC) + +static Scheme_Object *try_future_local_stack_overflow(Scheme_Object *rator, int argc, Scheme_Object **argv, int multi) + XFORM_SKIP_PROC +{ + if (SAME_TYPE(SCHEME_TYPE(rator), scheme_native_closure_type) + && scheme_can_apply_native_in_future(rator)) { + /* the only reason to get here is stack overflow, + either for the runstack or C stack */ + return scheme_rtcall_apply_with_new_stack(rator, argc, argv, multi); + } else if (multi) + return ts__scheme_apply_multi_from_native(rator, argc, argv); + else + return ts__scheme_apply_from_native(rator, argc, argv); +} + +static Scheme_Object *x_ts__scheme_apply_multi_from_native(Scheme_Object *rator, int argc, Scheme_Object **argv) + XFORM_SKIP_PROC +{ + if (scheme_use_rtcall) + return try_future_local_stack_overflow(rator, argc, argv, 1); + else + return _scheme_apply_multi_from_native(rator, argc, argv); +} + +static Scheme_Object *x_ts__scheme_apply_from_native(Scheme_Object *rator, int argc, Scheme_Object **argv) + XFORM_SKIP_PROC +{ + if (scheme_use_rtcall) + return try_future_local_stack_overflow(rator, argc, argv, 0); + else + return _scheme_apply_from_native(rator, argc, argv); +} + +#else +# define x_ts__scheme_apply_multi_from_native ts__scheme_apply_multi_from_native +# define x_ts__scheme_apply_from_native ts__scheme_apply_from_native +#endif + static int generate_pause_for_gc_and_retry(mz_jit_state *jitter, int in_short_jumps, int gc_reg, /* must not be JIT_R1 */ @@ -913,9 +952,9 @@ int scheme_generate_non_tail_call(mz_jit_state *jitter, int num_rands, int direc jit_pusharg_p(JIT_V1); if (num_rands < 0) { jit_movr_p(JIT_V1, JIT_R0); } /* save argc to manually pop runstack */ if (multi_ok) { - (void)mz_finish_lwe(ts__scheme_apply_multi_from_native, refrts); + (void)mz_finish_lwe(x_ts__scheme_apply_multi_from_native, refrts); } else { - (void)mz_finish_lwe(ts__scheme_apply_from_native, refrts); + (void)mz_finish_lwe(x_ts__scheme_apply_from_native, refrts); } CHECK_LIMIT(); mz_patch_ucbranch(ref5); diff --git a/src/racket/src/mzmark_future.inc b/src/racket/src/mzmark_future.inc index 87821e97e8..c09539050e 100644 --- a/src/racket/src/mzmark_future.inc +++ b/src/racket/src/mzmark_future.inc @@ -33,6 +33,7 @@ static int future_MARK(void *p, struct NewGC *gc) { gcMARK2(f->next_waiting_lwc, gc); gcMARK2(f->next_waiting_touch, gc); gcMARK2(f->suspended_lw, gc); + gcMARK2(f->suspended_lw_stack, gc); gcMARK2(f->prev_in_fsema_queue, gc); gcMARK2(f->next_in_fsema_queue, gc); gcMARK2(f->touching, gc); @@ -66,6 +67,7 @@ static int future_FIXUP(void *p, struct NewGC *gc) { gcFIXUP2(f->next_waiting_lwc, gc); gcFIXUP2(f->next_waiting_touch, gc); gcFIXUP2(f->suspended_lw, gc); + gcFIXUP2(f->suspended_lw_stack, gc); gcFIXUP2(f->prev_in_fsema_queue, gc); gcFIXUP2(f->next_in_fsema_queue, gc); gcFIXUP2(f->touching, gc); diff --git a/src/racket/src/mzmarksrc.c b/src/racket/src/mzmarksrc.c index bf645f96f9..cfc646784c 100644 --- a/src/racket/src/mzmarksrc.c +++ b/src/racket/src/mzmarksrc.c @@ -2474,6 +2474,7 @@ future { gcMARK2(f->next_waiting_lwc, gc); gcMARK2(f->next_waiting_touch, gc); gcMARK2(f->suspended_lw, gc); + gcMARK2(f->suspended_lw_stack, gc); gcMARK2(f->prev_in_fsema_queue, gc); gcMARK2(f->next_in_fsema_queue, gc); gcMARK2(f->touching, gc); diff --git a/src/racket/src/schpriv.h b/src/racket/src/schpriv.h index 9519c6a57f..148840ddfa 100644 --- a/src/racket/src/schpriv.h +++ b/src/racket/src/schpriv.h @@ -2457,6 +2457,8 @@ Scheme_Object *scheme_apply_lightweight_continuation(Scheme_Lightweight_Continua Scheme_Object **scheme_adjust_runstack_argument(Scheme_Lightweight_Continuation *captured, Scheme_Object **arg); +Scheme_Lightweight_Continuation *scheme_restore_lightweight_continuation_marks(Scheme_Lightweight_Continuation *lw); + int scheme_can_apply_lightweight_continuation(Scheme_Lightweight_Continuation *captured, int check_overflow);