avoid a jump in fast-path arity checking

svn: r14217
This commit is contained in:
Matthew Flatt 2009-03-22 16:22:05 +00:00
parent 8243dfaefb
commit bf499a4e05

View File

@ -7527,7 +7527,7 @@ static int generate_alloc_retry(mz_jit_state *jitter, int i)
typedef struct { typedef struct {
Scheme_Closure_Data *data; Scheme_Closure_Data *data;
void *code, *tail_code, *code_end, **patch_depth; void *arity_code, *code, *tail_code, *code_end, **patch_depth;
int max_extra, max_depth; int max_extra, max_depth;
Scheme_Native_Closure *nc; Scheme_Native_Closure *nc;
} Generate_Closure_Data; } Generate_Closure_Data;
@ -7536,8 +7536,8 @@ static int do_generate_closure(mz_jit_state *jitter, void *_data)
{ {
Generate_Closure_Data *gdata = (Generate_Closure_Data *)_data; Generate_Closure_Data *gdata = (Generate_Closure_Data *)_data;
Scheme_Closure_Data *data = gdata->data; Scheme_Closure_Data *data = gdata->data;
void *code, *tail_code, *code_end; void *code, *tail_code, *code_end, *arity_code;
int i, r, cnt, has_rest; int i, r, cnt, has_rest, is_method, num_params;
code = jit_get_ip().ptr; code = jit_get_ip().ptr;
@ -7554,6 +7554,34 @@ static int do_generate_closure(mz_jit_state *jitter, void *_data)
data->num_params); data->num_params);
CHECK_LIMIT(); CHECK_LIMIT();
/* A tail call with arity checking can start here.
(This is a little reundant checking when `code' is the
etry point, but that's the slow path anyway.) */
has_rest = ((SCHEME_CLOSURE_DATA_FLAGS(data) & CLOS_HAS_REST) ? 1 : 0);
is_method = ((SCHEME_CLOSURE_DATA_FLAGS(data) & CLOS_IS_METHOD) ? 1 : 0);
num_params = data->num_params;
if (num_params && has_rest)
--num_params;
if (num_params < MAX_SHARED_ARITY_CHECK) {
void *shared_arity_code;
shared_arity_code = shared_arity_check[num_params][has_rest][is_method];
if (!shared_arity_code) {
shared_arity_code = generate_lambda_simple_arity_check(num_params, has_rest, is_method, 1);
shared_arity_check[num_params][has_rest][is_method] = shared_arity_code;
}
arity_code = jit_get_ip().ptr;
if (!has_rest)
(void)jit_bnei_i(shared_arity_code, JIT_R1, num_params);
else
(void)jit_blti_i(shared_arity_code, JIT_R1, num_params);
} else
arity_code = generate_lambda_simple_arity_check(num_params, has_rest, is_method, 0);
/* A tail call starts here. Caller must ensure that the /* A tail call starts here. Caller must ensure that the
stack is big enough, right number of arguments, closure stack is big enough, right number of arguments, closure
is in R0. If the closure has a rest arg, also ensure is in R0. If the closure has a rest arg, also ensure
@ -7563,8 +7591,7 @@ static int do_generate_closure(mz_jit_state *jitter, void *_data)
/* 0 params and has_rest => (lambda args E) where args is not in E, /* 0 params and has_rest => (lambda args E) where args is not in E,
so accept any number of arguments and ignore them. */ so accept any number of arguments and ignore them. */
if ((SCHEME_CLOSURE_DATA_FLAGS(data) & CLOS_HAS_REST) if (has_rest && data->num_params) {
&& data->num_params) {
/* If runstack == argv and argc == cnt, then we didn't /* If runstack == argv and argc == cnt, then we didn't
copy args down, and we need to make room for scheme_null. */ copy args down, and we need to make room for scheme_null. */
jit_insn *ref, *ref2, *ref3; jit_insn *ref, *ref2, *ref3;
@ -7710,6 +7737,7 @@ static int do_generate_closure(mz_jit_state *jitter, void *_data)
code_end = jit_get_ip().ptr; code_end = jit_get_ip().ptr;
if (jitter->retain_start) { if (jitter->retain_start) {
gdata->arity_code = arity_code;
gdata->code = code; gdata->code = code;
gdata->tail_code = tail_code; gdata->tail_code = tail_code;
gdata->max_extra = jitter->max_extra_pushed; gdata->max_extra = jitter->max_extra_pushed;
@ -7727,7 +7755,7 @@ static void on_demand_generate_lambda(Scheme_Native_Closure *nc)
Scheme_Closure_Data *data; Scheme_Closure_Data *data;
Generate_Closure_Data gdata; Generate_Closure_Data gdata;
void *code, *tail_code, *arity_code; void *code, *tail_code, *arity_code;
int has_rest, is_method, num_params, max_depth; int max_depth;
data = ndata->u2.orig_code; data = ndata->u2.orig_code;
@ -7748,6 +7776,7 @@ static void on_demand_generate_lambda(Scheme_Native_Closure *nc)
if (SCHEME_CLOSURE_DATA_FLAGS(data) & CLOS_SINGLE_RESULT) if (SCHEME_CLOSURE_DATA_FLAGS(data) & CLOS_SINGLE_RESULT)
SCHEME_NATIVE_CLOSURE_DATA_FLAGS(ndata) |= NATIVE_IS_SINGLE_RESULT; SCHEME_NATIVE_CLOSURE_DATA_FLAGS(ndata) |= NATIVE_IS_SINGLE_RESULT;
arity_code = gdata.arity_code;
code = gdata.code; code = gdata.code;
tail_code = gdata.tail_code; tail_code = gdata.tail_code;
@ -7759,21 +7788,6 @@ static void on_demand_generate_lambda(Scheme_Native_Closure *nc)
#endif #endif
} }
has_rest = ((SCHEME_CLOSURE_DATA_FLAGS(data) & CLOS_HAS_REST) ? 1 : 0);
is_method = ((SCHEME_CLOSURE_DATA_FLAGS(data) & CLOS_IS_METHOD) ? 1 : 0);
num_params = data->num_params;
if (num_params && has_rest)
--num_params;
if (num_params < MAX_SHARED_ARITY_CHECK) {
arity_code = shared_arity_check[num_params][has_rest][is_method];
if (!arity_code) {
arity_code = generate_lambda_simple_arity_check(num_params, has_rest, is_method, 1);
shared_arity_check[num_params][has_rest][is_method] = arity_code;
}
} else
arity_code = generate_lambda_simple_arity_check(num_params, has_rest, is_method, 0);
/* Add a couple of extra slots to computed let-depth, in case /* Add a couple of extra slots to computed let-depth, in case
we haven't quite computed right for inlined uses, etc. */ we haven't quite computed right for inlined uses, etc. */
max_depth = WORDS_TO_BYTES(data->max_let_depth + gdata.max_extra + 2); max_depth = WORDS_TO_BYTES(data->max_let_depth + gdata.max_extra + 2);