diff --git a/racket/src/racket/src/jit.h b/racket/src/racket/src/jit.h index 9f6746d79e..b6a9137ba1 100644 --- a/racket/src/racket/src/jit.h +++ b/racket/src/racket/src/jit.h @@ -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 diff --git a/racket/src/racket/src/jit_ts.c b/racket/src/racket/src/jit_ts.c index 326557f752..392154a53d 100644 --- a/racket/src/racket/src/jit_ts.c +++ b/racket/src/racket/src/jit_ts.c @@ -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 diff --git a/racket/src/racket/src/jitcommon.c b/racket/src/racket/src/jitcommon.c index cfc53e8473..86e01617a8 100644 --- a/racket/src/racket/src/jitcommon.c +++ b/racket/src/racket/src/jitcommon.c @@ -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; } diff --git a/racket/src/racket/src/jitinline.c b/racket/src/racket/src/jitinline.c index ff47e3da65..02478cadd1 100644 --- a/racket/src/racket/src/jitinline.c +++ b/racket/src/racket/src/jitinline.c @@ -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) diff --git a/racket/src/racket/src/schpriv.h b/racket/src/racket/src/schpriv.h index 8f5e2c62fb..b572e0205d 100644 --- a/racket/src/racket/src/schpriv.h +++ b/racket/src/racket/src/schpriv.h @@ -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); diff --git a/racket/src/racket/src/string.c b/racket/src/racket/src/string.c index f794a5d324..4d31ff0a30 100644 --- a/racket/src/racket/src/string.c +++ b/racket/src/racket/src/string.c @@ -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?", 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 char string */ /**********************************************************************/