JIT: inline string=? and bytes=?

This commit is contained in:
Gustavo Massaccesi 2015-08-28 14:49:18 -03:00
parent 79738d3bf6
commit 152787cb0e
6 changed files with 240 additions and 13 deletions

View File

@ -359,6 +359,8 @@ struct scheme_jit_common_record {
void *with_immed_mark_code;
void *apply_to_list_tail_code, *apply_to_list_code, *apply_to_list_multi_ok_code;
void *eqv_code, *eqv_branch_code;
void *bad_string_eq_2_code;
void *bad_bytes_eq_2_code;
void *proc_arity_includes_code;
#ifdef CAN_INLINE_ALLOC

View File

@ -91,6 +91,8 @@ define_ts_s_s(scheme_extflvector_length, FSRC_MARKS)
define_ts_s_s(scheme_fxvector_length, FSRC_MARKS)
define_ts_s_s(scheme_string_length, FSRC_MARKS)
define_ts_s_s(scheme_byte_string_length, FSRC_MARKS)
define_ts_ss_s(scheme_string_eq_2, FSRC_MARKS)
define_ts_ss_s(scheme_byte_string_eq_2, FSRC_MARKS)
define_ts_s_s(scheme_unbox, FSRC_MARKS)
define_ts_si_s(scheme_struct_ref, FSRC_MARKS)
define_ts_sis_v(scheme_struct_set, FSRC_MARKS)
@ -218,6 +220,8 @@ define_ts_s_s(scheme_box, FSRC_OTHER)
# define ts_scheme_struct_ref scheme_struct_ref
# define ts_scheme_struct_set scheme_struct_set
# define ts_scheme_equal scheme_equal
# define ts_scheme_string_eq_2 scheme_string_eq_2
# define ts_scheme_byte_string_eq_2 scheme_byte_string_eq_2
# define ts_extract_one_cc_mark_to_tag extract_one_cc_mark_to_tag
# define ts_tail_call_with_values_from_multiple_result tail_call_with_values_from_multiple_result
# define ts_raise_bad_call_with_values raise_bad_call_with_values

View File

@ -629,6 +629,30 @@ static int common1b(mz_jit_state *jitter, void *_data)
CHECK_LIMIT();
scheme_jit_register_sub_func(jitter, sjc.bad_bytes_length_code, scheme_false);
/* *** bad_string_eq_2_code *** */
/* R0 and R1 are arguments */
sjc.bad_string_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_string_eq_2, ref);
CHECK_LIMIT();
scheme_jit_register_sub_func(jitter, sjc.bad_string_eq_2_code, 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;
}

View File

@ -2717,6 +2717,187 @@ int scheme_generate_inlined_binary(mz_jit_state *jitter, Scheme_App3_Rec *app, i
__END_SHORT_JUMPS__(branch_short);
return 1;
} else if (IS_NAMED_PRIM(rator, "string=?")
|| 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_false1, *ref_false2 = NULL;
GC_CAN_IGNORE jit_insn *ref_true1, *ref_true2, *ref_ucfinish;
GC_CAN_IGNORE jit_insn *ref_loop;
int is_str1, is_str2, len = 0;
int string, string_type;
void * sjc_bad_code;
intptr_t string_len_val, string_val;
if ((IS_NAMED_PRIM(rator, "string=?"))) {
string = 1;
string_type = scheme_char_string_type;
sjc_bad_code = sjc.bad_string_eq_2_code;
string_len_val = (intptr_t)&SCHEME_CHAR_STRLEN_VAL(0x0);
string_val = (intptr_t)&SCHEME_CHAR_STR_VAL(0x0);
} else if (IS_NAMED_PRIM(rator, "bytes=?")) {
string = 0;
string_type = scheme_byte_string_type;
sjc_bad_code = sjc.bad_bytes_eq_2_code;
string_len_val = (intptr_t)&SCHEME_BYTE_STRLEN_VAL(0x0);
string_val = (intptr_t)&SCHEME_BYTE_STR_VAL(0x0);
}
is_str1 = (SAME_TYPE(SCHEME_TYPE(app->rand1), string_type));
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();
if (need_sync) mz_rs_sync();
if (for_branch) {
__START_SHORT_JUMPS__(branch_short);
scheme_prepare_branch_jump(jitter, for_branch);
CHECK_LIMIT();
__END_SHORT_JUMPS__(branch_short);
}
__START_TINY_JUMPS__(1);
/* fail if either is not a string */
if (!is_str1) {
ref_fx1 = jit_bmsi_ul(jit_forward(), JIT_R0, 0x1);
jit_ldxi_s(JIT_R2, JIT_R0, &((Scheme_Object *)0x0)->type);
ref_fail1 = jit_bnei_i(jit_forward(), JIT_R2, string_type);
}
if (!is_str2) {
ref_fx2 = jit_bmsi_ul(jit_forward(), JIT_R1, 0x1);
jit_ldxi_s(JIT_V1, JIT_R1, &((Scheme_Object *)0x0)->type);
ref_fail2 = jit_bnei_i(jit_forward(), JIT_V1, string_type);
}
ref_ucnofail = jit_jmpi(jit_forward());
CHECK_LIMIT();
/* fail */
if (!is_str1) {
mz_patch_branch(ref_fx1);
mz_patch_branch(ref_fail1);
}
if (!is_str2) {
mz_patch_branch(ref_fx2);
mz_patch_branch(ref_fail2);
}
__END_TINY_JUMPS__(1);
(void)jit_calli(sjc_bad_code);
CHECK_LIMIT();
/* main */
__START_TINY_JUMPS__(1);
mz_patch_ucbranch(ref_ucnofail);
__END_TINY_JUMPS__(1);
if (result_ignored)
return 1;
/* false if they have different length */
__START_TINY_OR_SHORT_JUMPS__(!for_branch, branch_short);
if (is_str1) {
jit_ldxi_l(JIT_R2, JIT_R1, string_len_val);
ref_false1 = jit_bnei_l(jit_forward(), JIT_R2, len);
} else if (is_str2) {
jit_ldxi_l(JIT_R2, JIT_R0, string_len_val);
ref_false1 = jit_bnei_l(jit_forward(), JIT_R2, len);
} else {
jit_ldxi_l(JIT_R2, JIT_R0, string_len_val);
jit_ldxi_l(JIT_V1, JIT_R1, string_len_val);
ref_false1 = jit_bner_l(jit_forward(), JIT_R2, JIT_V1);
}
__END_TINY_OR_SHORT_JUMPS__(!for_branch, branch_short);
if ((!is_str1 && !is_str2) || len) {
__START_TINY_JUMPS__(1);
/* true if both have length zero or are eq?*/
ref_true1 = jit_beqi_l(jit_forward(), JIT_R2, 0);
ref_true2 = jit_beqr_p(jit_forward(), JIT_R0, JIT_R1);
/* initialize loop*/
jit_ldxi_p(JIT_R0, JIT_R0, string_val);
jit_ldxi_p(JIT_R1, JIT_R1, string_val);
CHECK_LIMIT();
/* main loop*/
if (string) {
ref_loop = jit_get_ip();
mz_set_local_p(JIT_R0, JIT_LOCAL3);
jit_ldr_i(JIT_R0, JIT_R0);
jit_ldr_i(JIT_V1, JIT_R1);
__END_TINY_JUMPS__(1);
__START_TINY_OR_SHORT_JUMPS__(!for_branch, branch_short);
ref_false2 = jit_bner_i(jit_forward(), JIT_R0, JIT_V1);
__END_TINY_OR_SHORT_JUMPS__(!for_branch, branch_short);
__START_TINY_JUMPS__(1);
mz_get_local_p(JIT_R0, JIT_LOCAL3);
jit_addi_p(JIT_R0, JIT_R0, 1 << LOG_MZCHAR_SIZE);
jit_addi_p(JIT_R1, JIT_R1, 1 << LOG_MZCHAR_SIZE);
jit_subi_l(JIT_R2, JIT_R2, 1);
(void)jit_bnei_l(ref_loop, JIT_R2, 0);
} else {
ref_loop = jit_get_ip();
mz_set_local_p(JIT_R0, JIT_LOCAL3);
jit_ldr_c(JIT_R0, JIT_R0);
jit_ldr_c(JIT_V1, JIT_R1);
__END_TINY_JUMPS__(1);
__START_TINY_OR_SHORT_JUMPS__(!for_branch, branch_short);
jit_extr_c_i(JIT_R0, JIT_R0);
jit_extr_c_i(JIT_V1, JIT_V1);
ref_false2 = jit_bner_i(jit_forward(), JIT_R0, JIT_V1);
__END_TINY_OR_SHORT_JUMPS__(!for_branch, branch_short);
__START_TINY_JUMPS__(1);
mz_get_local_p(JIT_R0, JIT_LOCAL3);
jit_addi_p(JIT_R0, JIT_R0, 1);
jit_addi_p(JIT_R1, JIT_R1, 1);
jit_subi_l(JIT_R2, JIT_R2, 1);
(void)jit_bnei_l(ref_loop, JIT_R2, 0);
}
CHECK_LIMIT();
/* true */
mz_patch_branch(ref_true1);
mz_patch_branch(ref_true2);
__END_TINY_JUMPS__(1);
}
if (for_branch) {
__START_SHORT_JUMPS__(branch_short);
scheme_add_branch_false(for_branch, ref_false1);
if (ref_false2)
scheme_add_branch_false(for_branch, ref_false2);
scheme_branch_for_true(jitter, for_branch);
__END_SHORT_JUMPS__(branch_short);
} else {
__START_TINY_JUMPS__(1);
jit_movi_p(dest, scheme_true);
ref_ucfinish = jit_jmpi(jit_forward());
/* false */
mz_patch_branch(ref_false1);
if (ref_false2)
mz_patch_branch(ref_false2);
jit_movi_p(dest, scheme_false);
/* finish */
mz_patch_ucbranch(ref_ucfinish);
__END_TINY_JUMPS__(1);
}
CHECK_LIMIT();
return 1;
} else if (IS_NAMED_PRIM(rator, "=")) {
scheme_generate_arith(jitter, rator, app->rand1, app->rand2, 2, 0, CMP_EQUAL, 0, for_branch, branch_short, 0, 0, NULL, dest);
@ -3147,7 +3328,7 @@ int scheme_generate_inlined_binary(mz_jit_state *jitter, Scheme_App3_Rec *app, i
} else {
if (unsafe) {
jit_rshi_ul(JIT_R1, JIT_R1, 1);
jit_ldxi_p(JIT_R0, JIT_R0, &SCHEME_CHAR_STR_VAL((Scheme_Object *)0x0));
jit_ldxi_p(JIT_R0, JIT_R0, &SCHEME_BYTE_STR_VAL((Scheme_Object *)0x0));
jit_ldxr_c(JIT_R0, JIT_R0, JIT_R1);
jit_extr_uc_ul(JIT_R0, JIT_R0);
jit_fixnum_l(dest, JIT_R0);
@ -3207,7 +3388,7 @@ int scheme_generate_inlined_binary(mz_jit_state *jitter, Scheme_App3_Rec *app, i
}
} else {
if (unsafe) {
jit_ldxi_p(JIT_R0, JIT_R0, &SCHEME_CHAR_STR_VAL((Scheme_Object *)0x0));
jit_ldxi_p(JIT_R0, JIT_R0, &SCHEME_BYTE_STR_VAL((Scheme_Object *)0x0));
jit_ldxr_c(JIT_R0, JIT_R0, JIT_V1);
jit_extr_uc_ul(JIT_R0, JIT_R0);
jit_fixnum_l(dest, JIT_R0);
@ -4221,7 +4402,7 @@ int scheme_generate_inlined_nary(mz_jit_state *jitter, Scheme_App_Rec *app, int
}
} else {
if (unsafe) {
jit_ldxi_p(JIT_R0, JIT_R0, &SCHEME_CHAR_STR_VAL((Scheme_Object *)0x0));
jit_ldxi_p(JIT_R0, JIT_R0, &SCHEME_BYTE_STR_VAL((Scheme_Object *)0x0));
jit_rshi_ul(JIT_R2, JIT_R2, 1);
jit_stxr_c(JIT_V1, JIT_R0, JIT_R2);
if (!result_ignored)

View File

@ -4121,9 +4121,11 @@ Scheme_Object *scheme_checked_set_mcdr (int argc, Scheme_Object *argv[]);
Scheme_Object *scheme_checked_vector_ref(int argc, Scheme_Object **argv);
Scheme_Object *scheme_checked_vector_set(int argc, Scheme_Object **argv);
Scheme_Object *scheme_string_length(Scheme_Object *v);
Scheme_Object *scheme_string_eq_2(Scheme_Object *str1, Scheme_Object *str2);
Scheme_Object *scheme_checked_string_ref(int argc, Scheme_Object *argv[]);
Scheme_Object *scheme_checked_string_set(int argc, Scheme_Object *argv[]);
Scheme_Object *scheme_byte_string_length(Scheme_Object *v);
Scheme_Object *scheme_byte_string_eq_2(Scheme_Object *str1, Scheme_Object *str2);
Scheme_Object *scheme_checked_byte_string_ref(int argc, Scheme_Object *argv[]);
Scheme_Object *scheme_checked_byte_string_set(int argc, Scheme_Object *argv[]);
Scheme_Object *scheme_checked_syntax_e(int argc, Scheme_Object **argv);

View File

@ -510,11 +510,10 @@ scheme_init_string (Scheme_Env *env)
SCHEME_PRIM_PROC_FLAGS(p) |= scheme_intern_prim_opt_flags(SCHEME_PRIM_IS_NARY_INLINED);
scheme_add_global_constant("string-set!", p, env);
scheme_add_global_constant("string=?",
scheme_make_immed_prim(string_eq,
"string=?",
2, -1),
env);
p = scheme_make_immed_prim(string_eq, "string=?", 2, -1);
SCHEME_PRIM_PROC_FLAGS(p) |= scheme_intern_prim_opt_flags(SCHEME_PRIM_IS_BINARY_INLINED);
scheme_add_global_constant("string=?", p, env);
scheme_add_global_constant("string-locale=?",
scheme_make_immed_prim(string_locale_eq,
"string-locale=?",
@ -788,11 +787,10 @@ scheme_init_string (Scheme_Env *env)
SCHEME_PRIM_PROC_FLAGS(p) |= scheme_intern_prim_opt_flags(SCHEME_PRIM_IS_NARY_INLINED);
scheme_add_global_constant("bytes-set!", p, env);
scheme_add_global_constant("bytes=?",
scheme_make_immed_prim(byte_string_eq,
"bytes=?",
2, -1),
env);
p = scheme_make_immed_prim(byte_string_eq, "bytes=?", 2, -1);
SCHEME_PRIM_PROC_FLAGS(p) |= scheme_intern_prim_opt_flags(SCHEME_PRIM_IS_BINARY_INLINED);
scheme_add_global_constant("bytes=?", p, env);
scheme_add_global_constant("bytes<?",
scheme_make_immed_prim(byte_string_lt,
"bytes<?",
@ -1202,6 +1200,14 @@ GEN_STRING_COMP(string_locale_ci_eq, "string-locale-ci=?", mz_char_strcmp_ci, ==
GEN_STRING_COMP(string_locale_ci_lt, "string-locale-ci<?", mz_char_strcmp_ci, <, 1, 0)
GEN_STRING_COMP(string_locale_ci_gt, "string-locale-ci>?", mz_char_strcmp_ci, >, 1, 0)
Scheme_Object *scheme_string_eq_2(Scheme_Object *str1, Scheme_Object *str2)
{
Scheme_Object *a[2];
a[0] = str1;
a[1] = str2;
return string_eq(2, a);
}
/**********************************************************************/
/* byte strings */
/**********************************************************************/
@ -1268,6 +1274,14 @@ GEN_BYTE_STRING_COMP(byte_string_gt, "bytes>?", mz_strcmp, >)
GEN_BYTE_STRING_PATH_COMP(path_lt, "path<?", mz_strcmp, <, SCHEME_PATHP, "path?")
Scheme_Object *scheme_byte_string_eq_2(Scheme_Object *str1, Scheme_Object *str2)
{
Scheme_Object *a[2];
a[0] = str1;
a[1] = str2;
return byte_string_eq(2, a);
}
/**********************************************************************/
/* byte string <-> char string */
/**********************************************************************/