JIT: Allow the jitter to reverse the arguments of string=?

This commit is contained in:
Gustavo Massaccesi 2016-08-05 00:21:29 -03:00
parent 6cad51189d
commit d4158c2b04
5 changed files with 106 additions and 54 deletions

View File

@ -4649,6 +4649,22 @@
(set! f 0)) (set! f 0))
#f) #f)
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Special case of folding for string=? and bytes=?
(test-comp '(lambda () (string=? "123" "123"))
'(lambda () #t))
(test-comp '(lambda () (string=? "123" "123456"))
'(lambda () #f))
(test-comp '(lambda () (string=? "123" "456"))
'(lambda () #f))
(test-comp '(lambda () (bytes=? #"123" #"123"))
'(lambda () #t))
(test-comp '(lambda () (bytes=? #"123" #"123456"))
'(lambda () #f))
(test-comp '(lambda () (bytes=? #"123" #"456"))
'(lambda () #f))
;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; Check that the type information is shifted in the ;; Check that the type information is shifted in the
;; right direction while inlining. ;; right direction while inlining.

View File

@ -358,7 +358,9 @@ struct scheme_jit_common_record {
void *apply_to_list_tail_code, *apply_to_list_code, *apply_to_list_multi_ok_code; void *apply_to_list_tail_code, *apply_to_list_code, *apply_to_list_multi_ok_code;
void *eqv_code, *eqv_branch_code; void *eqv_code, *eqv_branch_code;
void *bad_string_eq_2_code; void *bad_string_eq_2_code;
void *bad_string_rev_eq_2_code;
void *bad_bytes_eq_2_code; void *bad_bytes_eq_2_code;
void *bad_bytes_rev_eq_2_code;
void *proc_arity_includes_code; void *proc_arity_includes_code;
#ifdef CAN_INLINE_ALLOC #ifdef CAN_INLINE_ALLOC

View File

@ -469,8 +469,9 @@ static int common1(mz_jit_state *jitter, void *_data)
static int common1b(mz_jit_state *jitter, void *_data) static int common1b(mz_jit_state *jitter, void *_data)
{ {
int i; int i, j;
GC_CAN_IGNORE jit_insn *ref, *ref2; GC_CAN_IGNORE jit_insn *ref, *ref2;
void *ip;
/* *** bad_set_{car,cdr}_code and make_[fl]rectangular_code *** */ /* *** bad_set_{car,cdr}_code and make_[fl]rectangular_code *** */
/* Bad argument is in R0, other is in R1 */ /* Bad argument is in R0, other is in R1 */
@ -644,29 +645,40 @@ static int common1b(mz_jit_state *jitter, void *_data)
CHECK_LIMIT(); CHECK_LIMIT();
scheme_jit_register_sub_func(jitter, sjc.bad_bytes_length_code, scheme_false); scheme_jit_register_sub_func(jitter, sjc.bad_bytes_length_code, scheme_false);
/* *** bad_string_eq_2_code *** */ /* *** bad_[string/bytes]_[rev_]eq_2_code *** */
/* R0 and R1 are arguments */ /* R0 and R1 are arguments */
sjc.bad_string_eq_2_code = jit_get_ip(); for (i = 0; i < 2; i++) {
for (j = 0; j < 2; j++) {
ip = jit_get_ip();
if (i) {
if (j)
sjc.bad_bytes_rev_eq_2_code = ip;
else
sjc.bad_bytes_eq_2_code = ip;
} else {
if (j)
sjc.bad_string_rev_eq_2_code = ip;
else
sjc.bad_string_eq_2_code = ip;
}
mz_prolog(JIT_R2); mz_prolog(JIT_R2);
JIT_UPDATE_THREAD_RSPTR(); JIT_UPDATE_THREAD_RSPTR();
jit_prepare(2); jit_prepare(2);
if (j) {
jit_pusharg_p(JIT_R1); jit_pusharg_p(JIT_R1);
jit_pusharg_p(JIT_R0); jit_pusharg_p(JIT_R0);
} else {
jit_pusharg_p(JIT_R0);
jit_pusharg_p(JIT_R1);
}
if (i)
(void)mz_finish_lwe(ts_scheme_byte_string_eq_2, ref);
else
(void)mz_finish_lwe(ts_scheme_string_eq_2, ref); (void)mz_finish_lwe(ts_scheme_string_eq_2, ref);
CHECK_LIMIT(); CHECK_LIMIT();
scheme_jit_register_sub_func(jitter, sjc.bad_string_eq_2_code, scheme_false); scheme_jit_register_sub_func(jitter, ip, scheme_false);
}
/* *** bad_bytes_eq_2_code *** */ }
/* R0 and R1 are arguments */
sjc.bad_bytes_eq_2_code = jit_get_ip();
mz_prolog(JIT_R2);
JIT_UPDATE_THREAD_RSPTR();
jit_prepare(2);
jit_pusharg_p(JIT_R1);
jit_pusharg_p(JIT_R0);
(void)mz_finish_lwe(ts_scheme_byte_string_eq_2, ref);
CHECK_LIMIT();
scheme_jit_register_sub_func(jitter, sjc.bad_bytes_eq_2_code, scheme_false);
return 1; return 1;
} }

View File

@ -2205,7 +2205,7 @@ int scheme_generate_two_args(Scheme_Object *rand1, Scheme_Object *rand2, mz_jit_
/* de-sync's rs. /* de-sync's rs.
Results go into R0 and R1. If !order_matters, and if only the Results go into R0 and R1. If !order_matters, and if only the
second is simple, then the arguments will be in reverse order. second is simple, then the arguments will be in reverse order.
Return is 1 if thr arguments are in order, -1 if reversed. */ Return is 1 if the arguments are in order, -1 if reversed. */
{ {
int simple1, simple2, direction = 1; int simple1, simple2, direction = 1;
@ -2837,50 +2837,63 @@ int scheme_generate_inlined_binary(mz_jit_state *jitter, Scheme_App3_Rec *app, i
return 1; return 1;
} else if (IS_NAMED_PRIM(rator, "string=?") } else if (IS_NAMED_PRIM(rator, "string=?")
|| IS_NAMED_PRIM(rator, "bytes=?")) { || IS_NAMED_PRIM(rator, "bytes=?")) {
GC_CAN_IGNORE jit_insn *ref_fx1, *ref_fx2, *ref_fail1, *ref_fail2, *ref_ucnofail; GC_CAN_IGNORE jit_insn *ref_fx1 = NULL, *ref_fx2 = NULL, *ref_fail1 = NULL, *ref_fail2 = NULL;
GC_CAN_IGNORE jit_insn *ref_ucnofail;
GC_CAN_IGNORE jit_insn *ref_false1, *ref_false2 = NULL; GC_CAN_IGNORE jit_insn *ref_false1, *ref_false2 = NULL;
GC_CAN_IGNORE jit_insn *ref_true1, *ref_true2, *ref_ucfinish; GC_CAN_IGNORE jit_insn *ref_true1 = NULL, *ref_true2, *ref_ucfinish;
GC_CAN_IGNORE jit_insn *ref_loop; GC_CAN_IGNORE jit_insn *ref_loop;
int is_str1, is_str2, len = 0; Scheme_Object *rand1, *rand2;
int is_str1, is_str2, len = 0, direction = 0;
int string, string_type; int string, string_type;
void * sjc_bad_code; void *sjc_bad_code, *sjc_bad_rev_code;
intptr_t string_len_val, string_val; intptr_t string_len_val, string_val;
if ((IS_NAMED_PRIM(rator, "string=?"))) { if ((IS_NAMED_PRIM(rator, "string=?"))) {
string = 1; string = 1;
string_type = scheme_char_string_type; string_type = scheme_char_string_type;
sjc_bad_code = sjc.bad_string_eq_2_code; sjc_bad_code = sjc.bad_string_eq_2_code;
sjc_bad_rev_code = sjc.bad_string_rev_eq_2_code;
string_len_val = (intptr_t)&SCHEME_CHAR_STRLEN_VAL(0x0); string_len_val = (intptr_t)&SCHEME_CHAR_STRLEN_VAL(0x0);
string_val = (intptr_t)&SCHEME_CHAR_STR_VAL(0x0); string_val = (intptr_t)&SCHEME_CHAR_STR_VAL(0x0);
} else { /* IS_NAMED_PRIM(rator, "bytes=?") */ } else { /* IS_NAMED_PRIM(rator, "bytes=?") */
string = 0; string = 0;
string_type = scheme_byte_string_type; string_type = scheme_byte_string_type;
sjc_bad_code = sjc.bad_bytes_eq_2_code; sjc_bad_code = sjc.bad_bytes_eq_2_code;
sjc_bad_rev_code = sjc.bad_bytes_rev_eq_2_code;
string_len_val = (intptr_t)&SCHEME_BYTE_STRLEN_VAL(0x0); string_len_val = (intptr_t)&SCHEME_BYTE_STRLEN_VAL(0x0);
string_val = (intptr_t)&SCHEME_BYTE_STR_VAL(0x0); string_val = (intptr_t)&SCHEME_BYTE_STR_VAL(0x0);
} }
is_str1 = (SAME_TYPE(SCHEME_TYPE(app->rand1), string_type)); direction = scheme_generate_two_args(app->rand1, app->rand2, jitter, 0, 2);
is_str2 = (SAME_TYPE(SCHEME_TYPE(app->rand2), string_type));
if (string) {
if (is_str1) {
len = SCHEME_CHAR_STRLEN_VAL(app->rand1);
} else if (is_str2) {
len = SCHEME_CHAR_STRLEN_VAL(app->rand2);
}
} else {
if (is_str1) {
len = SCHEME_BYTE_STRLEN_VAL(app->rand1);
} else if (is_str2) {
len = SCHEME_BYTE_STRLEN_VAL(app->rand2);
}
}
scheme_generate_two_args(app->rand1, app->rand2, jitter, 1, 2);
CHECK_LIMIT(); CHECK_LIMIT();
mz_rs_sync(); mz_rs_sync();
if (direction == -1) {
rand1 = app->rand2;
rand2 = app->rand1;
} else {
rand1 = app->rand1;
rand2 = app->rand2;
}
is_str1 = (SAME_TYPE(SCHEME_TYPE(rand1), string_type));
is_str2 = (SAME_TYPE(SCHEME_TYPE(rand2), string_type));
if (string) {
if (is_str1) {
len = SCHEME_CHAR_STRLEN_VAL(rand1);
} else if (is_str2) {
len = SCHEME_CHAR_STRLEN_VAL(rand2);
}
} else {
if (is_str1) {
len = SCHEME_BYTE_STRLEN_VAL(rand1);
} else if (is_str2) {
len = SCHEME_BYTE_STRLEN_VAL(rand2);
}
}
if (for_branch) { if (for_branch) {
__START_SHORT_JUMPS__(branch_short); __START_SHORT_JUMPS__(branch_short);
scheme_prepare_branch_jump(jitter, for_branch); scheme_prepare_branch_jump(jitter, for_branch);
@ -2894,17 +2907,11 @@ int scheme_generate_inlined_binary(mz_jit_state *jitter, Scheme_App3_Rec *app, i
ref_fx1 = jit_bmsi_ul(jit_forward(), JIT_R0, 0x1); ref_fx1 = jit_bmsi_ul(jit_forward(), JIT_R0, 0x1);
jit_ldxi_s(JIT_R2, JIT_R0, &((Scheme_Object *)0x0)->type); jit_ldxi_s(JIT_R2, JIT_R0, &((Scheme_Object *)0x0)->type);
ref_fail1 = jit_bnei_i(jit_forward(), JIT_R2, string_type); ref_fail1 = jit_bnei_i(jit_forward(), JIT_R2, string_type);
} else {
ref_fx1 = NULL;
ref_fail1 = NULL;
} }
if (!is_str2) { if (!is_str2) {
ref_fx2 = jit_bmsi_ul(jit_forward(), JIT_R1, 0x1); ref_fx2 = jit_bmsi_ul(jit_forward(), JIT_R1, 0x1);
jit_ldxi_s(JIT_V1, JIT_R1, &((Scheme_Object *)0x0)->type); jit_ldxi_s(JIT_V1, JIT_R1, &((Scheme_Object *)0x0)->type);
ref_fail2 = jit_bnei_i(jit_forward(), JIT_V1, string_type); ref_fail2 = jit_bnei_i(jit_forward(), JIT_V1, string_type);
} else {
ref_fx2 = NULL;
ref_fail2 = NULL;
} }
ref_ucnofail = jit_jmpi(jit_forward()); ref_ucnofail = jit_jmpi(jit_forward());
CHECK_LIMIT(); CHECK_LIMIT();
@ -2920,7 +2927,10 @@ int scheme_generate_inlined_binary(mz_jit_state *jitter, Scheme_App3_Rec *app, i
} }
__END_TINY_JUMPS__(1); __END_TINY_JUMPS__(1);
if (direction == 1)
(void)jit_calli(sjc_bad_code); (void)jit_calli(sjc_bad_code);
else
(void)jit_calli(sjc_bad_rev_code);
CHECK_LIMIT(); CHECK_LIMIT();
/* main */ /* main */
@ -2949,6 +2959,7 @@ int scheme_generate_inlined_binary(mz_jit_state *jitter, Scheme_App3_Rec *app, i
if ((!is_str1 && !is_str2) || len) { if ((!is_str1 && !is_str2) || len) {
__START_TINY_JUMPS__(1); __START_TINY_JUMPS__(1);
/* true if both have length zero or are eq?*/ /* true if both have length zero or are eq?*/
if (!len)
ref_true1 = jit_beqi_l(jit_forward(), JIT_R2, 0); ref_true1 = jit_beqi_l(jit_forward(), JIT_R2, 0);
ref_true2 = jit_beqr_p(jit_forward(), JIT_R0, JIT_R1); ref_true2 = jit_beqr_p(jit_forward(), JIT_R0, JIT_R1);
@ -2994,6 +3005,7 @@ int scheme_generate_inlined_binary(mz_jit_state *jitter, Scheme_App3_Rec *app, i
CHECK_LIMIT(); CHECK_LIMIT();
/* true */ /* true */
if (ref_true1)
mz_patch_branch(ref_true1); mz_patch_branch(ref_true1);
mz_patch_branch(ref_true2); mz_patch_branch(ref_true2);
__END_TINY_JUMPS__(1); __END_TINY_JUMPS__(1);

View File

@ -4622,6 +4622,16 @@ static Scheme_Object *finish_optimize_application3(Scheme_App3_Rec *app, Optimiz
info->size -= 1; info->size -= 1;
return make_optimize_prim_application2(scheme_null_p_proc, app->rand1, info, context); return make_optimize_prim_application2(scheme_null_p_proc, app->rand1, info, context);
} }
} else if (IS_NAMED_PRIM(app->rator, "string=?")) {
if (SAME_TYPE(SCHEME_TYPE(app->rand1), scheme_char_string_type)
&& SAME_TYPE(SCHEME_TYPE(app->rand2), scheme_char_string_type)) {
return scheme_string_eq_2(app->rand1, app->rand2);
}
} else if (IS_NAMED_PRIM(app->rator, "bytes=?")) {
if (SAME_TYPE(SCHEME_TYPE(app->rand1), scheme_byte_string_type)
&& SAME_TYPE(SCHEME_TYPE(app->rand2), scheme_byte_string_type)) {
return scheme_byte_string_eq_2(app->rand1, app->rand2);
}
} }
} }