fix futures bug related to GC
When a future is blocked on JIT generation, a lightweight closure is captured, and then the future moves on, the runtime thread would correctly shift the on-demand JIT argument to the captured copy of the runstack. However, it would also add 2 to that pointer to use as the argv array, and the captured runstack is not allocated to allow interior pointers, so a GC during on-demand JIT could crash. The solution is to keep an offset alongside the argv pointer during JITting.
This commit is contained in:
parent
7a5e90f48f
commit
958352eefc
|
@ -1180,7 +1180,7 @@ static Scheme_Object *make_future(Scheme_Object *lambda)
|
|||
/* JIT the code if not already JITted */
|
||||
if (ncd) {
|
||||
if (ncd->code == scheme_on_demand_jit_code)
|
||||
scheme_on_demand_generate_lambda(nc, 0, NULL);
|
||||
scheme_on_demand_generate_lambda(nc, 0, NULL, 0);
|
||||
|
||||
if (ncd->max_let_depth > FUTURE_RUNSTACK_SIZE * sizeof(void*)) {
|
||||
/* Can't even call it in a future thread */
|
||||
|
@ -2139,24 +2139,24 @@ static Scheme_Object *_apply_future_lw(future_t *ft)
|
|||
{
|
||||
struct Scheme_Lightweight_Continuation *lw = ft->suspended_lw;
|
||||
Scheme_Object *v;
|
||||
int result_is_rs_argv;
|
||||
int result_is_rs_plus_two;
|
||||
|
||||
ft->suspended_lw = NULL;
|
||||
|
||||
v = ft->retval_s;
|
||||
if (ft->retval_is_rs_argv) {
|
||||
result_is_rs_argv = 1;
|
||||
ft->retval_is_rs_argv = 0;
|
||||
if (ft->retval_is_rs_plus_two) {
|
||||
result_is_rs_plus_two = 1;
|
||||
ft->retval_is_rs_plus_two = 0;
|
||||
} else {
|
||||
ft->retval_s = NULL;
|
||||
receive_special_result(ft, v, 1);
|
||||
result_is_rs_argv = 0;
|
||||
result_is_rs_plus_two = 0;
|
||||
}
|
||||
|
||||
FUTURE_ASSERT((ft->prim_protocol != SIG_ON_DEMAND) == !result_is_rs_argv);
|
||||
FUTURE_ASSERT((ft->prim_protocol != SIG_ON_DEMAND) == !result_is_rs_plus_two);
|
||||
FUTURE_ASSERT(v || (ft->prim_protocol != SIG_ALLOC));
|
||||
|
||||
v = scheme_apply_lightweight_continuation(lw, v, result_is_rs_argv,
|
||||
v = scheme_apply_lightweight_continuation(lw, v, result_is_rs_plus_two,
|
||||
FUTURE_RUNSTACK_SIZE);
|
||||
|
||||
if (SAME_OBJ(v, SCHEME_TAIL_CALL_WAITING)) {
|
||||
|
@ -2568,10 +2568,7 @@ Scheme_Object **scheme_rtcall_on_demand(const char *who, int src_type, prim_on_d
|
|||
|
||||
future->prim_protocol = SIG_ON_DEMAND;
|
||||
|
||||
if ((MZ_RUNSTACK + 2) != argv) {
|
||||
fprintf(stderr, "internal error: expected arguments on runstack");
|
||||
abort();
|
||||
}
|
||||
FUTURE_ASSERT(argv == (MZ_RUNSTACK + 2));
|
||||
|
||||
future->arg_S0 = MZ_RUNSTACK;
|
||||
|
||||
|
@ -2585,7 +2582,7 @@ Scheme_Object **scheme_rtcall_on_demand(const char *who, int src_type, prim_on_d
|
|||
future = fts->thread->current_ft;
|
||||
|
||||
future->arg_S0 = NULL;
|
||||
future->retval_is_rs_argv = 0;
|
||||
future->retval_is_rs_plus_two = 0;
|
||||
|
||||
return MZ_RUNSTACK + 2;
|
||||
}
|
||||
|
@ -2898,9 +2895,9 @@ static void do_invoke_rtcall(Scheme_Future_State *fs, future_t *future, int is_a
|
|||
|
||||
ADJUST_RS_ARG(future, arg_S0);
|
||||
|
||||
func(arg_S0, arg_S0 + 2);
|
||||
func(arg_S0, arg_S0, 2);
|
||||
|
||||
future->retval_is_rs_argv = 1;
|
||||
future->retval_is_rs_plus_two = 1;
|
||||
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
#ifdef MZ_USE_FUTURES
|
||||
|
||||
typedef Scheme_Object **(*prim_on_demand_t)(Scheme_Object **, Scheme_Object **);
|
||||
typedef Scheme_Object **(*prim_on_demand_t)(Scheme_Object **, Scheme_Object **, int);
|
||||
typedef Scheme_Object* (*prim_obj_int_pobj_obj_t)(Scheme_Object*, int, Scheme_Object**);
|
||||
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*);
|
||||
|
@ -144,7 +144,8 @@ typedef struct future_t {
|
|||
void *retval_p; /* use only with conservative GC */
|
||||
MZ_MARK_STACK_TYPE retval_m;
|
||||
int retval_i;
|
||||
int no_retval, retval_is_rs_argv;
|
||||
char no_retval;
|
||||
char retval_is_rs_plus_two; /* => special result handling for on-demand JIT */
|
||||
|
||||
Scheme_Object **multiple_array;
|
||||
int multiple_count;
|
||||
|
|
|
@ -483,7 +483,7 @@ Scheme_Object *scheme_extract_closure_local(Scheme_Object *obj, mz_jit_state *ji
|
|||
a closure element into an argument */
|
||||
pos -= jitter->closure_to_args_delta;
|
||||
if (pos < jitter->example_argc)
|
||||
return jitter->example_argv[pos];
|
||||
return jitter->example_argv[pos + jitter->example_argv_delta];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3042,7 +3042,7 @@ typedef struct {
|
|||
void *arity_code, *code, *tail_code, *code_end, **patch_depth;
|
||||
int max_extra, max_depth, max_tail_depth;
|
||||
Scheme_Native_Closure *nc;
|
||||
int argc;
|
||||
int argc, argv_delta;
|
||||
Scheme_Object **argv;
|
||||
} Generate_Closure_Data;
|
||||
|
||||
|
@ -3051,7 +3051,7 @@ static int do_generate_closure(mz_jit_state *jitter, void *_data)
|
|||
Generate_Closure_Data *gdata = (Generate_Closure_Data *)_data;
|
||||
Scheme_Closure_Data *data = gdata->data;
|
||||
void *code, *tail_code, *code_end, *arity_code;
|
||||
int i, r, cnt, has_rest, is_method, num_params, to_args, argc;
|
||||
int i, r, cnt, has_rest, is_method, num_params, to_args, argc, argv_delta;
|
||||
Scheme_Object **argv;
|
||||
|
||||
code = jit_get_ip().ptr;
|
||||
|
@ -3060,6 +3060,7 @@ static int do_generate_closure(mz_jit_state *jitter, void *_data)
|
|||
|
||||
argc = gdata->argc;
|
||||
argv = gdata->argv;
|
||||
argv_delta = gdata->argv_delta;
|
||||
|
||||
generate_function_prolog(jitter, code,
|
||||
/* max_extra_pushed may be wrong the first time around,
|
||||
|
@ -3347,6 +3348,7 @@ static int do_generate_closure(mz_jit_state *jitter, void *_data)
|
|||
jitter->closure_to_args_delta = to_args;
|
||||
jitter->example_argc = argc;
|
||||
jitter->example_argv = argv;
|
||||
jitter->example_argv_delta = argv_delta;
|
||||
|
||||
/* Generate code for the body: */
|
||||
jitter->need_set_rs = 1;
|
||||
|
@ -3380,7 +3382,7 @@ static int do_generate_closure(mz_jit_state *jitter, void *_data)
|
|||
return 1;
|
||||
}
|
||||
|
||||
static void on_demand_generate_lambda(Scheme_Native_Closure *nc, int argc, Scheme_Object **argv)
|
||||
static void on_demand_generate_lambda(Scheme_Native_Closure *nc, int argc, Scheme_Object **argv, int argv_delta)
|
||||
{
|
||||
Scheme_Native_Closure_Data *ndata = nc->code;
|
||||
Scheme_Closure_Data *data;
|
||||
|
@ -3394,6 +3396,7 @@ static void on_demand_generate_lambda(Scheme_Native_Closure *nc, int argc, Schem
|
|||
gdata.nc = nc;
|
||||
gdata.argc = argc;
|
||||
gdata.argv = argv;
|
||||
gdata.argv_delta = argv_delta;
|
||||
|
||||
/* This action is not atomic: */
|
||||
scheme_delay_load_closure(data);
|
||||
|
@ -3461,28 +3464,28 @@ static void on_demand_generate_lambda(Scheme_Native_Closure *nc, int argc, Schem
|
|||
ndata->max_let_depth = max_depth;
|
||||
}
|
||||
|
||||
void scheme_on_demand_generate_lambda(Scheme_Native_Closure *nc, int argc, Scheme_Object **argv)
|
||||
void scheme_on_demand_generate_lambda(Scheme_Native_Closure *nc, int argc, Scheme_Object **argv, int argv_delta)
|
||||
{
|
||||
on_demand_generate_lambda(nc, argc, argv);
|
||||
on_demand_generate_lambda(nc, argc, argv, argv_delta);
|
||||
}
|
||||
|
||||
Scheme_Object **scheme_on_demand_with_args(Scheme_Object **in_argv, Scheme_Object **argv)
|
||||
Scheme_Object **scheme_on_demand_with_args(Scheme_Object **in_argv, Scheme_Object **argv, int argv_delta)
|
||||
{
|
||||
/* On runstack: closure (nearest), argc, argv (deepest) */
|
||||
/* On runstack: closure (nearest), argc, probably argv (deepest) */
|
||||
Scheme_Object *c, *argc;
|
||||
|
||||
c = in_argv[0];
|
||||
argc = in_argv[1];
|
||||
|
||||
if (((Scheme_Native_Closure *)c)->code->code == scheme_on_demand_jit_code)
|
||||
scheme_on_demand_generate_lambda((Scheme_Native_Closure *)c, SCHEME_INT_VAL(argc), argv);
|
||||
scheme_on_demand_generate_lambda((Scheme_Native_Closure *)c, SCHEME_INT_VAL(argc), argv, argv_delta);
|
||||
|
||||
return argv;
|
||||
}
|
||||
|
||||
Scheme_Object **scheme_on_demand(Scheme_Object **rs)
|
||||
{
|
||||
return scheme_on_demand_with_args(MZ_RUNSTACK, rs);
|
||||
return scheme_on_demand_with_args(MZ_RUNSTACK, rs, 0);
|
||||
}
|
||||
|
||||
static Scheme_Native_Closure_Data *create_native_lambda(Scheme_Closure_Data *data, int clear_code_after_jit,
|
||||
|
|
|
@ -313,7 +313,7 @@ typedef struct mz_jit_state {
|
|||
int self_pos, self_closure_size, self_toplevel_pos;
|
||||
int self_to_closure_delta, closure_to_args_delta;
|
||||
int closure_self_on_runstack;
|
||||
int example_argc;
|
||||
int example_argc, example_argv_delta;
|
||||
Scheme_Object **example_argv;
|
||||
void *self_restart_code;
|
||||
void *self_nontail_code;
|
||||
|
@ -1242,7 +1242,7 @@ int scheme_generate_non_tail_mark_pos_prefix(mz_jit_state *jitter);
|
|||
void scheme_generate_non_tail_mark_pos_suffix(mz_jit_state *jitter);
|
||||
|
||||
Scheme_Object **scheme_on_demand(Scheme_Object **argv);
|
||||
Scheme_Object **scheme_on_demand_with_args(Scheme_Object **in_argv, Scheme_Object **argv);
|
||||
Scheme_Object **scheme_on_demand_with_args(Scheme_Object **in_argv, Scheme_Object **argv, int argv_delta);
|
||||
|
||||
void scheme_prepare_branch_jump(mz_jit_state *jitter, Branch_Info *for_branch);
|
||||
void scheme_branch_for_true(mz_jit_state *jitter, Branch_Info *for_branch);
|
||||
|
|
|
@ -1455,7 +1455,7 @@ int scheme_generate_app(Scheme_App_Rec *app, Scheme_Object **alt_rands, int num_
|
|||
nc = (Scheme_Native_Closure *)scheme_jit_closure((Scheme_Object *)data, NULL);
|
||||
if (nc->code->code == scheme_on_demand_jit_code) {
|
||||
if (nc->code->arity_code != sjc.in_progress_on_demand_jit_arity_code) {
|
||||
scheme_on_demand_generate_lambda(nc, 0, NULL);
|
||||
scheme_on_demand_generate_lambda(nc, 0, NULL, 0);
|
||||
}
|
||||
}
|
||||
if (nc->code->code != scheme_on_demand_jit_code) {
|
||||
|
|
|
@ -2691,7 +2691,7 @@ Scheme_Object *scheme_jit_closure(Scheme_Object *, Scheme_Object *context);
|
|||
void scheme_jit_fill_threadlocal_table();
|
||||
|
||||
#ifdef MZ_USE_JIT
|
||||
void scheme_on_demand_generate_lambda(Scheme_Native_Closure *nc, int argc, Scheme_Object **argv);
|
||||
void scheme_on_demand_generate_lambda(Scheme_Native_Closure *nc, int argc, Scheme_Object **argv, int delta);
|
||||
#endif
|
||||
|
||||
struct Start_Module_Args;
|
||||
|
|
Loading…
Reference in New Issue
Block a user