more consistently clear the tail-call and multiple-values buffers

More consistent clearing avoids a kind of space unsafety. There's just
one buffer per thread, so it's difficult to turn non-clearing into
a detectable leak (I wasn't abel to construct an example), but it
might be possible. More practically, failing to clear the buffer
can make it difficult to debug memory use.
This commit is contained in:
Matthew Flatt 2012-11-03 10:26:19 -06:00
parent 7ee6a814e5
commit eaf1fd1fe5
17 changed files with 166 additions and 71 deletions

View File

@ -180,6 +180,7 @@ EXPORTS
scheme_set_tail_buffer_size
scheme_force_value
scheme_force_one_value
scheme_ignore_result
scheme_set_cont_mark
scheme_push_continuation_frame
scheme_pop_continuation_frame

View File

@ -180,6 +180,7 @@ EXPORTS
scheme_set_tail_buffer_size
scheme_force_value
scheme_force_one_value
scheme_ignore_result
scheme_set_cont_mark
scheme_push_continuation_frame
scheme_pop_continuation_frame

View File

@ -188,6 +188,7 @@ scheme_tail_eval_expr
scheme_set_tail_buffer_size
scheme_force_value
scheme_force_one_value
scheme_ignore_result
scheme_set_cont_mark
scheme_push_continuation_frame
scheme_pop_continuation_frame

View File

@ -188,6 +188,7 @@ scheme_tail_eval_expr
scheme_set_tail_buffer_size
scheme_force_value
scheme_force_one_value
scheme_ignore_result
scheme_set_cont_mark
scheme_push_continuation_frame
scheme_pop_continuation_frame

View File

@ -371,6 +371,18 @@ void scheme_init_eval_places()
#endif
}
XFORM_NONGCING static void ignore_result(Scheme_Object *v)
{
if (SAME_OBJ(v, SCHEME_MULTIPLE_VALUES)) {
scheme_current_thread->ku.multiple.array = NULL;
}
}
void scheme_ignore_result(Scheme_Object *v)
{
ignore_result(v);
}
/*========================================================================*/
/* C stack and Scheme stack handling */
/*========================================================================*/
@ -1903,9 +1915,9 @@ define_execute_with_dynamic_state(Scheme_Object *vec, int delta, int defmacro,
int is_st;
values = scheme_current_thread->ku.multiple.array;
scheme_current_thread->ku.multiple.array = NULL;
if (SAME_OBJ(values, scheme_current_thread->values_buffer))
scheme_current_thread->values_buffer = NULL;
scheme_current_thread->ku.multiple.array = NULL;
if (dm_env)
is_st = 0;
@ -1946,10 +1958,10 @@ define_execute_with_dynamic_state(Scheme_Object *vec, int delta, int defmacro,
scheme_pop_prefix(save_runstack);
return scheme_void;
}
} else {
if (SAME_OBJ(scheme_current_thread->ku.multiple.array, scheme_current_thread->values_buffer))
scheme_current_thread->values_buffer = NULL;
}
} else if (SCHEME_VEC_SIZE(vec) == delta + 1) { /* => single var */
var = SCHEME_VEC_ELS(vec)[delta];
if (dm_env) {
@ -2096,6 +2108,7 @@ static Scheme_Object *apply_values_execute(Scheme_Object *data)
v = _scheme_eval_linked_expr_multi(SCHEME_PTR2_VAL(data));
if (SAME_OBJ(v, SCHEME_MULTIPLE_VALUES)) {
Scheme_Thread *p = scheme_current_thread;
Scheme_Object **rands;
int num_rands = p->ku.multiple.count;
if (num_rands > p->tail_buffer_size) {
@ -2103,7 +2116,9 @@ static Scheme_Object *apply_values_execute(Scheme_Object *data)
if (SAME_OBJ(p->ku.multiple.array, p->values_buffer))
p->values_buffer = NULL;
}
return scheme_tail_apply(f, num_rands, p->ku.multiple.array);
rands = p->ku.multiple.array;
p->ku.multiple.array = NULL;
return scheme_tail_apply(f, num_rands, rands);
} else {
Scheme_Object *a[1];
a[0] = v;
@ -2223,7 +2238,7 @@ static Scheme_Object *begin0_execute(Scheme_Object *obj)
apos = 1;
while (i--) {
(void)_scheme_eval_linked_expr_multi(((Scheme_Sequence *)obj)->array[apos++]);
ignore_result(_scheme_eval_linked_expr_multi(((Scheme_Sequence *)obj)->array[apos++]));
}
if (mv) {
@ -2247,7 +2262,7 @@ static Scheme_Object *splice_execute(Scheme_Object *data)
int i, cnt = seq->count - 1;
for (i = 0; i < cnt; i++) {
(void)_scheme_call_with_prompt_multi(splice_one_expr, seq->array[i]);
ignore_result(_scheme_call_with_prompt_multi(splice_one_expr, seq->array[i]));
}
return _scheme_eval_linked_expr_multi(seq->array[cnt]);
@ -2327,7 +2342,7 @@ do_define_syntaxes_execute(Scheme_Object *form, Scheme_Env *dm_env)
save_runstack = scheme_push_prefix(dm_env->exp_env, rp, NULL, NULL, 1, 1, NULL, scheme_false);
while (!SCHEME_NULLP(form)) {
(void)scheme_eval_linked_expr_multi_with_dynamic_state(SCHEME_CAR(form), &dyn_state);
ignore_result(scheme_eval_linked_expr_multi_with_dynamic_state(SCHEME_CAR(form), &dyn_state));
form = SCHEME_CDR(form);
}
@ -3407,7 +3422,7 @@ scheme_do_eval(Scheme_Object *obj, int num_rands, Scheme_Object **rands,
UPDATE_THREAD_RSPTR();
for (i = 0; i < cnt; i++) {
(void)_scheme_eval_linked_expr_multi_wp(((Scheme_Sequence *)obj)->array[i], p);
ignore_result(_scheme_eval_linked_expr_multi_wp(((Scheme_Sequence *)obj)->array[i], p));
}
obj = ((Scheme_Sequence *)obj)->array[cnt];
@ -5192,6 +5207,7 @@ static Scheme_Object *do_eval_string_all(Scheme_Object *port, const char *str, S
if (SAME_OBJ(p->ku.multiple.array, p->values_buffer))
p->values_buffer = NULL;
a = p->ku.multiple.array;
p->ku.multiple.array = NULL;
cnt = p->ku.multiple.count;
} else {
_a[0] = result;

View File

@ -3402,7 +3402,8 @@ Scheme_Object *scheme_apply_chaperone(Scheme_Object *o, int argc, Scheme_Object
GC_CAN_IGNORE Scheme_Thread *p = scheme_current_thread;
c = p->ku.multiple.count;
argv2 = p->ku.multiple.array;
if (SAME_OBJ(p->ku.multiple.array, p->values_buffer)) {
p->ku.multiple.array = NULL;
if (SAME_OBJ(argv2, p->values_buffer)) {
if (c <= MAX_QUICK_CHAP_ARGV) {
for (i = 0; i < c; i++) {
a2[i] = argv2[i];
@ -3544,6 +3545,7 @@ Scheme_Object *scheme_apply_chaperone(Scheme_Object *o, int argc, Scheme_Object
p->values_buffer = NULL;
c = p->ku.multiple.count;
argv = p->ku.multiple.array;
p->ku.multiple.array = NULL;
} else {
c = 1;
a[0] = v;
@ -3575,6 +3577,7 @@ Scheme_Object *scheme_apply_chaperone(Scheme_Object *o, int argc, Scheme_Object
p->values_buffer = NULL;
argc = p->ku.multiple.count;
argv2 = p->ku.multiple.array;
p->ku.multiple.array = NULL;
} else {
argc = 1;
a2[0] = v;
@ -3713,9 +3716,9 @@ static Scheme_Object *call_with_values(int argc, Scheme_Object *argv[])
Scheme_Object **a;
if (SAME_OBJ(p->ku.multiple.array, p->values_buffer))
p->values_buffer = NULL;
/* Beware: the fields overlap! */
n = p->ku.multiple.count;
a = p->ku.multiple.array;
p->ku.multiple.array = NULL;
p->ku.apply.tail_num_rands = n;
p->ku.apply.tail_rands = a;
} else {
@ -5110,6 +5113,7 @@ static void restore_continuation(Scheme_Cont *cont, Scheme_Thread *p, int for_pr
mc = p->ku.multiple.count;
if (SAME_OBJ(mv, p->values_buffer))
p->values_buffer = NULL;
p->ku.multiple.array = NULL;
} else {
mv = NULL;
mc = 0;
@ -6394,6 +6398,7 @@ static Scheme_Object **chaperone_do_control(const char *name, int mode,
p->values_buffer = NULL;
num_args = p->ku.multiple.count;
vals = p->ku.multiple.array;
p->ku.multiple.array = NULL;
} else {
num_args = 1;
vals = MALLOC_N(Scheme_Object *, 1);
@ -6470,6 +6475,7 @@ static Scheme_Object *do_cc_guard(Scheme_Object *v, Scheme_Object *cc_guard, Sch
p->values_buffer = NULL;
argc = p->ku.multiple.count;
argv = p->ku.multiple.array;
p->ku.multiple.array = NULL;
} else {
a[0] = v;
argv = a;
@ -8591,7 +8597,7 @@ static void pre_post_dyn_wind(Scheme_Object *prepost)
scheme_push_break_enable(&cframe, 0, 0);
/* Here's the main call: */
(void)_scheme_apply_multi(prepost, 0, NULL);
scheme_ignore_result(_scheme_apply_multi(prepost, 0, NULL));
scheme_pop_break_enable(&cframe, 0);
@ -9441,10 +9447,12 @@ static Scheme_Object *time_apply(int argc, Scheme_Object *argv[])
if (v == SCHEME_MULTIPLE_VALUES) {
Scheme_Thread *cp = scheme_current_thread;
Scheme_Object **args;
if (SAME_OBJ(cp->ku.multiple.array, cp->values_buffer))
cp->values_buffer = NULL;
v = scheme_build_list(cp->ku.multiple.count,
cp->ku.multiple.array);
args = cp->ku.multiple.array;
cp->ku.multiple.array = NULL;
v = scheme_build_list(cp->ku.multiple.count, args);
} else
v = scheme_make_pair(v, scheme_null);

View File

@ -2276,8 +2276,12 @@ int scheme_generate(Scheme_Object *obj, mz_jit_state *jitter, int is_tail, int w
(void)jit_jmpi(refloop);
CHECK_LIMIT();
mz_patch_branch(ref3);
/* clear array pointer and re-laod argc: */
(void)mz_tl_ldi_p(JIT_R0, tl_scheme_current_thread);
(void)jit_movi_p(JIT_R1, NULL);
jit_stxi_l(&((Scheme_Thread *)0x0)->ku.multiple.array, JIT_R0, JIT_R1);
jit_ldxi_l(JIT_R0, JIT_R0, &((Scheme_Thread *)0x0)->ku.multiple.count);
CHECK_LIMIT();
/* Perform call --------------------- */
/* Function is in V1, argc in R0, args on RUNSTACK */
@ -2286,16 +2290,18 @@ int scheme_generate(Scheme_Object *obj, mz_jit_state *jitter, int is_tail, int w
if (is_tail) {
if (!sjc.shared_tail_argc_code) {
sjc.shared_tail_argc_code = scheme_generate_shared_call(-1, jitter, 1, 1, 0, 0, 0, 0);
sjc.shared_tail_argc_code = scheme_generate_shared_call(-1, jitter, 1, 0, 1, 0, 0, 0, 0);
}
mz_set_local_p(JIT_R0, JIT_LOCAL2);
(void)jit_jmpi(sjc.shared_tail_argc_code);
} else {
int mo = multi_ok ? 1 : 0;
int mo = (multi_ok
? (result_ignored ? SHARED_RESULT_IGNORED_CASE : SHARED_MULTI_OK_CASE)
: SHARED_SINGLE_VALUE_CASE);
void *code;
if (!sjc.shared_non_tail_argc_code[mo]) {
scheme_ensure_retry_available(jitter, multi_ok);
code = scheme_generate_shared_call(-2, jitter, multi_ok, 0, 0, 0, 0, 0);
scheme_ensure_retry_available(jitter, multi_ok, result_ignored);
code = scheme_generate_shared_call(-2, jitter, multi_ok, result_ignored, 0, 0, 0, 0, 0);
sjc.shared_non_tail_argc_code[mo] = code;
}
code = sjc.shared_non_tail_argc_code[mo];
@ -2438,7 +2444,7 @@ int scheme_generate(Scheme_Object *obj, mz_jit_state *jitter, int is_tail, int w
return r;
}
r = scheme_generate_app(app, NULL, app->num_args, jitter, is_tail, multi_ok, 0);
r = scheme_generate_app(app, NULL, app->num_args, jitter, is_tail, multi_ok, result_ignored, 0);
CHECK_LIMIT();
if (target != JIT_R0)
@ -2468,7 +2474,7 @@ int scheme_generate(Scheme_Object *obj, mz_jit_state *jitter, int is_tail, int w
args[0] = app->rator;
args[1] = app->rand;
r = scheme_generate_app(NULL, args, 1, jitter, is_tail, multi_ok, 0);
r = scheme_generate_app(NULL, args, 1, jitter, is_tail, multi_ok, result_ignored, 0);
CHECK_LIMIT();
if (target != JIT_R0)
@ -2499,7 +2505,7 @@ int scheme_generate(Scheme_Object *obj, mz_jit_state *jitter, int is_tail, int w
args[1] = app->rand1;
args[2] = app->rand2;
r = scheme_generate_app(NULL, args, 2, jitter, is_tail, multi_ok, 0);
r = scheme_generate_app(NULL, args, 2, jitter, is_tail, multi_ok, result_ignored, 0);
CHECK_LIMIT();
if (target != JIT_R0)
@ -2601,9 +2607,9 @@ int scheme_generate(Scheme_Object *obj, mz_jit_state *jitter, int is_tail, int w
/* Did we get multiple results? If not, go to error: */
ref = jit_bnei_p(jit_forward(), JIT_R0, SCHEME_MULTIPLE_VALUES);
/* Load count and result array: */
mz_tl_ldi_p(JIT_R2, tl_scheme_current_thread);
jit_ldxi_l(JIT_R1, JIT_R2, &((Scheme_Thread *)0x0)->ku.multiple.count);
jit_ldxi_p(JIT_R2, JIT_R2, &((Scheme_Thread *)0x0)->ku.multiple.array);
mz_tl_ldi_p(JIT_V1, tl_scheme_current_thread);
jit_ldxi_p(JIT_R2, JIT_V1, &((Scheme_Thread *)0x0)->ku.multiple.array);
jit_ldxi_l(JIT_R1, JIT_V1, &((Scheme_Thread *)0x0)->ku.multiple.count);
CHECK_LIMIT();
/* If we got the expected count, jump to installing values: */
ref2 = jit_beqi_i(jit_forward(), JIT_R1, lv->count);
@ -2630,9 +2636,11 @@ int scheme_generate(Scheme_Object *obj, mz_jit_state *jitter, int is_tail, int w
(void)mz_finish_lwe(ts_lexical_binding_wrong_return_arity, ref);
CHECK_LIMIT();
/* Continue with expected values; R2 has value array: */
/* Continue with expected values; R2 has values and V1 has thread pointer: */
mz_patch_branch(ref2);
__END_SHORT_JUMPS__(1);
(void)jit_movi_p(JIT_R0, NULL);
jit_stxi_p(&((Scheme_Thread *)0x0)->ku.multiple.array, JIT_V1, JIT_R0);
for (i = 0; i < lv->count; i++) {
jit_ldxi_p(JIT_R1, JIT_R2, WORDS_TO_BYTES(i));
if (ab) {

View File

@ -210,9 +210,13 @@ struct scheme_jit_common_record {
#define MAX_SHARED_CALL_RANDS 25
void *shared_tail_code[4][MAX_SHARED_CALL_RANDS];
void *shared_non_tail_code[5][MAX_SHARED_CALL_RANDS][2];
void *shared_non_tail_retry_code[2];
void *shared_non_tail_argc_code[2];
# define SHARED_SINGLE_VALUE_CASE 0
# define SHARED_MULTI_OK_CASE 1
# define SHARED_RESULT_IGNORED_CASE 2
# define SHARED_NUM_NONTAIL_CASES 3
void *shared_non_tail_code[5][MAX_SHARED_CALL_RANDS][SHARED_NUM_NONTAIL_CASES];
void *shared_non_tail_retry_code[SHARED_NUM_NONTAIL_CASES];
void *shared_non_tail_argc_code[SHARED_NUM_NONTAIL_CASES];
void *shared_tail_argc_code;
#define MAX_SHARED_ARITY_CHECK 25
@ -1228,15 +1232,17 @@ int scheme_generate_arith(mz_jit_state *jitter, Scheme_Object *rator, Scheme_Obj
typedef struct jit_direct_arg jit_direct_arg;
void *scheme_generate_shared_call(int num_rands, mz_jit_state *old_jitter, int multi_ok, int is_tail,
int direct_prim, int direct_native, int nontail_self, int unboxed_args);
void scheme_ensure_retry_available(mz_jit_state *jitter, int multi_ok);
void *scheme_generate_shared_call(int num_rands, mz_jit_state *old_jitter, int multi_ok, int result_ignored,
int is_tail, int direct_prim, int direct_native, int nontail_self, int unboxed_args);
void scheme_ensure_retry_available(mz_jit_state *jitter, int multi_ok, int result_ignored);
int scheme_generate_app(Scheme_App_Rec *app, Scheme_Object **alt_rands, int num_rands,
mz_jit_state *jitter, int is_tail, int multi_ok, int no_call);
mz_jit_state *jitter, int is_tail, int multi_ok, int ignored_result,
int no_call);
int scheme_generate_tail_call(mz_jit_state *jitter, int num_rands, int direct_native, int need_set_rs,
int is_inline, Scheme_Native_Closure *direct_to_code, jit_direct_arg *direct_arg);
int scheme_generate_non_tail_call(mz_jit_state *jitter, int num_rands, int direct_native, int need_set_rs,
int multi_ok, int nontail_self, int pop_and_jump, int is_inlined, int unboxed_args);
int multi_ok, int result_ignored, int nontail_self, int pop_and_jump,
int is_inlined, int unboxed_args);
int scheme_generate_finish_tail_call(mz_jit_state *jitter, int direct_native);
int scheme_generate_finish_apply(mz_jit_state *jitter);
int scheme_generate_finish_multi_apply(mz_jit_state *jitter);

View File

@ -1920,7 +1920,7 @@ int scheme_generate_nary_arith(mz_jit_state *jitter, Scheme_App_Rec *app,
}
if (stack_c)
scheme_generate_app(app, alt_args, stack_c, jitter, 0, 0, 2);
scheme_generate_app(app, alt_args, stack_c, jitter, 0, 0, 0, 2);
CHECK_LIMIT();
mz_rs_sync();

View File

@ -604,7 +604,8 @@ static int generate_direct_prim_non_tail_call(mz_jit_state *jitter, int num_rand
return 1;
}
static int generate_retry_call(mz_jit_state *jitter, int num_rands, int multi_ok, GC_CAN_IGNORE jit_insn *reftop)
static int generate_retry_call(mz_jit_state *jitter, int num_rands, int multi_ok, int result_ignored,
GC_CAN_IGNORE jit_insn *reftop)
/* If num_rands < 0, original argc is in V1, and we should
pop argc arguments off runstack before pushing more.
This function is called with short jumps enabled. */
@ -612,7 +613,10 @@ static int generate_retry_call(mz_jit_state *jitter, int num_rands, int multi_ok
GC_CAN_IGNORE jit_insn *ref, *ref2, *refloop;
if (!reftop) {
reftop = sjc.shared_non_tail_retry_code[multi_ok ? 1 : 0];
int mo = (multi_ok
? (result_ignored ? SHARED_RESULT_IGNORED_CASE : SHARED_MULTI_OK_CASE)
: SHARED_SINGLE_VALUE_CASE);
reftop = sjc.shared_non_tail_retry_code[mo];
}
/* Get new argc: */
@ -637,7 +641,7 @@ static int generate_retry_call(mz_jit_state *jitter, int num_rands, int multi_ok
/* Copy arguments to runstack, then jump to reftop. */
jit_ldxi_l(JIT_R2, JIT_R1, &((Scheme_Thread *)0x0)->ku.apply.tail_num_rands);
jit_ldxi_l(JIT_V1, JIT_R1, &((Scheme_Thread *)0x0)->ku.apply.tail_rands);
jit_ldxi_p(JIT_V1, JIT_R1, &((Scheme_Thread *)0x0)->ku.apply.tail_rands);
jit_lshi_l(JIT_R2, JIT_R2, JIT_LOG_WORD_SIZE);
CHECK_LIMIT();
refloop = _jit.x.pc;
@ -648,10 +652,15 @@ static int generate_retry_call(mz_jit_state *jitter, int num_rands, int multi_ok
(void)jit_jmpi(refloop);
CHECK_LIMIT();
/* Clear tail-call arguments pointer: */
(void)jit_movi_p(JIT_V1, NULL);
jit_stxi_p(&((Scheme_Thread *)0x0)->ku.apply.tail_rands, JIT_R1, JIT_V1);
CHECK_LIMIT();
/* R1 is still the thread.
Put procedure and argc in place, then jump to apply: */
mz_patch_branch(ref2);
jit_ldxi_l(JIT_V1, JIT_R1, &((Scheme_Thread *)0x0)->ku.apply.tail_rator);
jit_ldxi_p(JIT_V1, JIT_R1, &((Scheme_Thread *)0x0)->ku.apply.tail_rator);
jit_ldxi_l(JIT_R0, JIT_R1, &((Scheme_Thread *)0x0)->ku.apply.tail_num_rands);
__END_SHORT_JUMPS__(1);
(void)jit_jmpi(reftop);
@ -690,9 +699,28 @@ static int generate_clear_slow_previous_args(mz_jit_state *jitter)
return 1;
}
static int generate_ignored_result_check(mz_jit_state *jitter)
{
/* if multiple results, need to clear ignored result in thread */
GC_CAN_IGNORE jit_insn *refm;
__START_INNER_TINY__(1);
refm = jit_bnei_p(jit_forward(), JIT_R0, SCHEME_MULTIPLE_VALUES);
mz_tl_ldi_p(JIT_R1, tl_scheme_current_thread);
(void)jit_movi_p(JIT_R0, NULL);
jit_stxi_p(&((Scheme_Thread *)0x0)->ku.multiple.array, JIT_R1, JIT_R0);
(void)jit_movi_p(JIT_R0, scheme_void);
mz_patch_branch(refm);
__END_INNER_TINY__(1);
return 1;
}
int scheme_generate_non_tail_call(mz_jit_state *jitter, int num_rands, int direct_native, int need_set_rs,
int multi_ok, int nontail_self, int pop_and_jump, int is_inlined,
int unboxed_args)
int multi_ok, int result_ignored, int nontail_self, int pop_and_jump,
int is_inlined, int unboxed_args)
{
/* Non-tail call.
Proc is in V1, args are at RUNSTACK.
@ -876,7 +904,7 @@ int scheme_generate_non_tail_call(mz_jit_state *jitter, int num_rands, int direc
CHECK_LIMIT();
if (pop_and_jump) {
/* Expects argc in V1 if num_rands < 0: */
generate_retry_call(jitter, num_rands, multi_ok, reftop);
generate_retry_call(jitter, num_rands, multi_ok, result_ignored, reftop);
}
CHECK_LIMIT();
if (need_set_rs) {
@ -939,7 +967,7 @@ int scheme_generate_non_tail_call(mz_jit_state *jitter, int num_rands, int direc
CHECK_LIMIT();
if (pop_and_jump) {
/* Expects argc in V1 if num_rands < 0: */
generate_retry_call(jitter, num_rands, multi_ok, reftop);
generate_retry_call(jitter, num_rands, multi_ok, result_ignored, reftop);
}
CHECK_LIMIT();
if (num_rands < 0) {
@ -1023,6 +1051,10 @@ int scheme_generate_non_tail_call(mz_jit_state *jitter, int num_rands, int direc
mz_patch_branch(ref6);
if (!direct_native) {
mz_patch_branch(ref10);
if (result_ignored) {
generate_ignored_result_check(jitter);
CHECK_LIMIT();
}
}
/* Note: same return code is above for faster common-case return */
if (num_rands < 0) {
@ -1237,6 +1269,7 @@ typedef struct {
int num_rands;
mz_jit_state *old_jitter;
int multi_ok;
int result_ignored;
int is_tail;
int direct_prim, direct_native, nontail_self, unboxed_args;
} Generate_Call_Data;
@ -1295,7 +1328,8 @@ static int do_generate_shared_call(mz_jit_state *jitter, void *_data)
ok = generate_direct_prim_non_tail_call(jitter, data->num_rands, data->multi_ok, 1);
else
ok = scheme_generate_non_tail_call(jitter, data->num_rands, data->direct_native, 1,
data->multi_ok, data->nontail_self, 1, 0, data->unboxed_args);
data->multi_ok, data->result_ignored, data->nontail_self,
1, 0, data->unboxed_args);
scheme_jit_register_sub_func(jitter, code, scheme_false);
@ -1303,14 +1337,16 @@ static int do_generate_shared_call(mz_jit_state *jitter, void *_data)
}
}
void *scheme_generate_shared_call(int num_rands, mz_jit_state *old_jitter, int multi_ok, int is_tail,
int direct_prim, int direct_native, int nontail_self, int unboxed_args)
void *scheme_generate_shared_call(int num_rands, mz_jit_state *old_jitter, int multi_ok, int result_ignored,
int is_tail, int direct_prim, int direct_native, int nontail_self,
int unboxed_args)
{
Generate_Call_Data data;
data.num_rands = num_rands;
data.old_jitter = old_jitter;
data.multi_ok = multi_ok;
data.result_ignored = result_ignored;
data.is_tail = is_tail;
data.direct_prim = direct_prim;
data.direct_native = direct_native;
@ -1320,12 +1356,14 @@ void *scheme_generate_shared_call(int num_rands, mz_jit_state *old_jitter, int m
return scheme_generate_one(old_jitter, do_generate_shared_call, &data, 0, NULL, NULL);
}
void scheme_ensure_retry_available(mz_jit_state *jitter, int multi_ok)
void scheme_ensure_retry_available(mz_jit_state *jitter, int multi_ok, int result_ignored)
{
int mo = multi_ok ? 1 : 0;
int mo = (multi_ok
? (result_ignored ? SHARED_RESULT_IGNORED_CASE : SHARED_MULTI_OK_CASE)
: SHARED_SINGLE_VALUE_CASE);
if (!sjc.shared_non_tail_retry_code[mo]) {
void *code;
code = scheme_generate_shared_call(-1, jitter, multi_ok, 0, 0, 0, 0, 0);
code = scheme_generate_shared_call(-1, jitter, multi_ok, result_ignored, 0, 0, 0, 0, 0);
sjc.shared_non_tail_retry_code[mo] = code;
}
}
@ -1586,7 +1624,8 @@ static int generate_call_path_with_unboxes(mz_jit_state *jitter, int direct_flos
#endif
int scheme_generate_app(Scheme_App_Rec *app, Scheme_Object **alt_rands, int num_rands,
mz_jit_state *jitter, int is_tail, int multi_ok, int no_call)
mz_jit_state *jitter, int is_tail, int multi_ok, int result_ignored,
int no_call)
/* de-sync'd ok
If no_call is 2, then rator is not necssarily evaluated.
If no_call is 1, then rator is left in V1 and arguments are on runstack. */
@ -1624,6 +1663,8 @@ int scheme_generate_app(Scheme_App_Rec *app, Scheme_Object **alt_rands, int num_
if ((num_rands >= 2) && SAME_OBJ(rator, scheme_apply_proc))
apply_to_list = 1;
}
if (!(((Scheme_Primitive_Proc *)rator)->pp.flags & SCHEME_PRIM_IS_MULTI_RESULT))
result_ignored = 0; /* don't need to check for multiple values to ignore */
} else {
Scheme_Type t;
t = SCHEME_TYPE(rator);
@ -1970,7 +2011,7 @@ int scheme_generate_app(Scheme_App_Rec *app, Scheme_Object **alt_rands, int num_
generate_nontail_self_setup(jitter);
}
scheme_generate_non_tail_call(jitter, num_rands, direct_native, jitter->need_set_rs,
multi_ok, nontail_self, 0, 1, 0);
multi_ok, result_ignored, nontail_self, 0, 1, 0);
}
}
} else {
@ -1981,7 +2022,8 @@ int scheme_generate_app(Scheme_App_Rec *app, Scheme_Object **alt_rands, int num_
if (is_tail) {
if (!sjc.shared_tail_code[dp][num_rands]) {
code = scheme_generate_shared_call(num_rands, jitter, multi_ok, is_tail, direct_prim, direct_native, 0, 0);
code = scheme_generate_shared_call(num_rands, jitter, multi_ok, result_ignored, is_tail,
direct_prim, direct_native, 0, 0);
sjc.shared_tail_code[dp][num_rands] = code;
}
code = sjc.shared_tail_code[dp][num_rands];
@ -2024,7 +2066,9 @@ int scheme_generate_app(Scheme_App_Rec *app, Scheme_Object **alt_rands, int num_
}
}
} else {
int mo = (multi_ok ? 1 : 0);
int mo = (multi_ok
? (result_ignored ? SHARED_RESULT_IGNORED_CASE : SHARED_MULTI_OK_CASE)
: SHARED_SINGLE_VALUE_CASE);
#ifdef USE_FLONUM_UNBOXING
void *unboxed_code;
#endif
@ -2035,8 +2079,9 @@ int scheme_generate_app(Scheme_App_Rec *app, Scheme_Object **alt_rands, int num_
#ifdef USE_FLONUM_UNBOXING
if (unboxed_non_tail_args) {
if (!sjc.shared_non_tail_code[4][num_rands][mo]) {
scheme_ensure_retry_available(jitter, multi_ok);
code = scheme_generate_shared_call(num_rands, jitter, multi_ok, is_tail, direct_prim, direct_native, nontail_self, 1);
scheme_ensure_retry_available(jitter, multi_ok, result_ignored);
code = scheme_generate_shared_call(num_rands, jitter, multi_ok, result_ignored, is_tail,
direct_prim, direct_native, nontail_self, 1);
sjc.shared_non_tail_code[4][num_rands][mo] = code;
}
unboxed_code = sjc.shared_non_tail_code[4][num_rands][mo];
@ -2045,8 +2090,9 @@ int scheme_generate_app(Scheme_App_Rec *app, Scheme_Object **alt_rands, int num_
#endif
if (!sjc.shared_non_tail_code[dp][num_rands][mo]) {
scheme_ensure_retry_available(jitter, multi_ok);
code = scheme_generate_shared_call(num_rands, jitter, multi_ok, is_tail, direct_prim, direct_native, nontail_self, 0);
scheme_ensure_retry_available(jitter, multi_ok, result_ignored);
code = scheme_generate_shared_call(num_rands, jitter, multi_ok, result_ignored, is_tail,
direct_prim, direct_native, nontail_self, 0);
sjc.shared_non_tail_code[dp][num_rands][mo] = code;
}
LOG_IT(("<-non-tail %d %d %d\n", dp, num_rands, mo));

View File

@ -979,7 +979,7 @@ static int generate_apply_proxy(mz_jit_state *jitter, int setter)
CHECK_LIMIT();
JIT_UPDATE_THREAD_RSPTR();
__END_SHORT_JUMPS__(1);
scheme_generate_non_tail_call(jitter, 3, 0, 0, 0, 0, 0, 1, 0);
scheme_generate_non_tail_call(jitter, 3, 0, 0, 0, 0, 0, 0, 1, 0);
__START_SHORT_JUMPS__(1);
CHECK_LIMIT();
if (setter) {
@ -3041,7 +3041,7 @@ static int more_common0(mz_jit_state *jitter, void *_data)
mz_rs_sync();
__END_SHORT_JUMPS__(1);
scheme_generate_non_tail_call(jitter, 2, 0, 1, 0, 0, 0, 0, 0);
scheme_generate_non_tail_call(jitter, 2, 0, 1, 0, 0, 0, 0, 0, 0);
CHECK_LIMIT();
__START_SHORT_JUMPS__(1);
@ -3476,7 +3476,7 @@ static int more_common1(mz_jit_state *jitter, void *_data)
__END_SHORT_JUMPS__(1);
scheme_generate_non_tail_call(jitter, -1, 0, 1, multi_ok, 0, 1, 0, 0);
scheme_generate_non_tail_call(jitter, -1, 0, 1, multi_ok, 0, 0, 1, 0, 0);
scheme_jit_register_sub_func(jitter, code, scheme_false);
}

View File

@ -383,7 +383,7 @@ static int generate_inlined_struct_op(int kind, mz_jit_state *jitter,
args[0] = rator;
args[1] = rand;
args[2] = rand2;
scheme_generate_app(NULL, args, 2, jitter, 0, 0, 1); /* sync'd below */
scheme_generate_app(NULL, args, 2, jitter, 0, 0, 0, 1); /* sync'd below */
CHECK_LIMIT();
jit_movr_p(JIT_R0, JIT_V1);
mz_rs_ldr(JIT_R1);
@ -600,7 +600,7 @@ static int generate_inlined_nary_struct_op(int kind, mz_jit_state *jitter,
/* de-sync'd ok; for branch, sync'd before */
{
/* generate code to evaluate the arguments */
scheme_generate_app(app, NULL, app->num_args, jitter, 0, 0, 1);
scheme_generate_app(app, NULL, app->num_args, jitter, 0, 0, 0, 1);
CHECK_LIMIT();
mz_rs_sync();
@ -3165,7 +3165,7 @@ int scheme_generate_inlined_binary(mz_jit_state *jitter, Scheme_App3_Rec *app, i
args[1] = app->rand1;
args[2] = app->rand2;
scheme_generate_app(NULL, args, 2, jitter, 0, 0, 2);
scheme_generate_app(NULL, args, 2, jitter, 0, 0, 0, 2);
CHECK_LIMIT();
mz_rs_sync();
@ -3271,7 +3271,7 @@ int scheme_generate_inlined_nary(mz_jit_state *jitter, Scheme_App_Rec *app, int
}
/* generate code to evaluate the arguments */
scheme_generate_app(app, NULL, 3, jitter, 0, 0, 2);
scheme_generate_app(app, NULL, 3, jitter, 0, 0, 0, 2);
CHECK_LIMIT();
mz_rs_sync();
@ -3680,7 +3680,7 @@ int scheme_generate_inlined_nary(mz_jit_state *jitter, Scheme_App_Rec *app, int
} else {
got_two = 1;
mz_runstack_skipped(jitter, 1);
scheme_generate_app(app, NULL, 2, jitter, 0, 0, 2);
scheme_generate_app(app, NULL, 2, jitter, 0, 0, 0, 2);
}
if (scheme_can_unbox_inline(app->args[3], 5, JIT_FPR_NUM-1, 1))
@ -3737,7 +3737,7 @@ int scheme_generate_inlined_nary(mz_jit_state *jitter, Scheme_App_Rec *app, int
star = IS_NAMED_PRIM(rator, "list*");
if (c)
scheme_generate_app(app, NULL, c, jitter, 0, 0, 2);
scheme_generate_app(app, NULL, c, jitter, 0, 0, 0, 2);
CHECK_LIMIT();
mz_rs_sync();
@ -3775,7 +3775,7 @@ int scheme_generate_inlined_nary(mz_jit_state *jitter, Scheme_App_Rec *app, int
if (!multi_ok) return 0;
if (c) {
scheme_generate_app(app, NULL, c, jitter, 0, 0, 2);
scheme_generate_app(app, NULL, c, jitter, 0, 0, 0, 2);
CHECK_LIMIT();
mz_rs_sync();
@ -3812,7 +3812,7 @@ int scheme_generate_inlined_nary(mz_jit_state *jitter, Scheme_App_Rec *app, int
} else if (IS_NAMED_PRIM(rator, "max")) {
return scheme_generate_nary_arith(jitter, app, ARITH_MAX, 0, NULL, 1);
} else if (IS_NAMED_PRIM(rator, "checked-procedure-check-and-extract")) {
scheme_generate_app(app, NULL, 5, jitter, 0, 0, 2); /* sync'd below */
scheme_generate_app(app, NULL, 5, jitter, 0, 0, 0, 2); /* sync'd below */
CHECK_LIMIT();
mz_rs_sync();
@ -3893,7 +3893,7 @@ static int generate_vector_alloc(mz_jit_state *jitter, Scheme_Object *rator,
} else {
c = app->num_args;
if (c)
scheme_generate_app(app, NULL, c, jitter, 0, 0, 2); /* sync'd below */
scheme_generate_app(app, NULL, c, jitter, 0, 0, 0, 2); /* sync'd below */
}
CHECK_LIMIT();

View File

@ -5536,7 +5536,9 @@ static Scheme_Object *body_one_expr(void *prefix_plus_expr, int argc, Scheme_Obj
v = _scheme_eval_linked_expr_multi(SCHEME_CDR((Scheme_Object *)prefix_plus_expr));
scheme_suspend_prefix(saved_runstack);
return v;
scheme_ignore_result(v);
return scheme_void;
}
static int needs_prompt(Scheme_Object *e)
@ -5632,7 +5634,7 @@ void *scheme_module_run_finish(Scheme_Env *menv, Scheme_Env *env)
scheme_make_raw_pair(save_prefix, body));
scheme_resume_prefix(save_prefix);
} else
(void)_scheme_eval_linked_expr_multi(body);
scheme_ignore_result(_scheme_eval_linked_expr_multi(body));
}
if (scheme_module_demand_hook) {

View File

@ -361,6 +361,8 @@ MZ_EXTERN void scheme_set_tail_buffer_size(int s);
MZ_EXTERN Scheme_Object *scheme_force_value(Scheme_Object *);
MZ_EXTERN Scheme_Object *scheme_force_one_value(Scheme_Object *);
XFORM_NONGCING MZ_EXTERN void scheme_ignore_result(Scheme_Object *);
MZ_EXTERN MZ_MARK_STACK_TYPE scheme_set_cont_mark(Scheme_Object *key, Scheme_Object *val);
MZ_EXTERN void scheme_push_continuation_frame(Scheme_Cont_Frame_Data *);
MZ_EXTERN void scheme_pop_continuation_frame(Scheme_Cont_Frame_Data *);

View File

@ -278,6 +278,7 @@ Scheme_Object *(*scheme_tail_eval_expr)(Scheme_Object *obj);
void (*scheme_set_tail_buffer_size)(int s);
Scheme_Object *(*scheme_force_value)(Scheme_Object *);
Scheme_Object *(*scheme_force_one_value)(Scheme_Object *);
void (*scheme_ignore_result)(Scheme_Object *);
MZ_MARK_STACK_TYPE (*scheme_set_cont_mark)(Scheme_Object *key, Scheme_Object *val);
void (*scheme_push_continuation_frame)(Scheme_Cont_Frame_Data *);
void (*scheme_pop_continuation_frame)(Scheme_Cont_Frame_Data *);

View File

@ -196,6 +196,7 @@
scheme_extension_table->scheme_set_tail_buffer_size = scheme_set_tail_buffer_size;
scheme_extension_table->scheme_force_value = scheme_force_value;
scheme_extension_table->scheme_force_one_value = scheme_force_one_value;
scheme_extension_table->scheme_ignore_result = scheme_ignore_result;
scheme_extension_table->scheme_set_cont_mark = scheme_set_cont_mark;
scheme_extension_table->scheme_push_continuation_frame = scheme_push_continuation_frame;
scheme_extension_table->scheme_pop_continuation_frame = scheme_pop_continuation_frame;

View File

@ -196,6 +196,7 @@
#define scheme_set_tail_buffer_size (scheme_extension_table->scheme_set_tail_buffer_size)
#define scheme_force_value (scheme_extension_table->scheme_force_value)
#define scheme_force_one_value (scheme_extension_table->scheme_force_one_value)
#define scheme_ignore_result (scheme_extension_table->scheme_ignore_result)
#define scheme_set_cont_mark (scheme_extension_table->scheme_set_cont_mark)
#define scheme_push_continuation_frame (scheme_extension_table->scheme_push_continuation_frame)
#define scheme_pop_continuation_frame (scheme_extension_table->scheme_pop_continuation_frame)