diff --git a/vlib/v/gen/c/auto_eq_methods.v b/vlib/v/gen/c/auto_eq_methods.v index 50374d8352ee53..6e10e8733b6955 100644 --- a/vlib/v/gen/c/auto_eq_methods.v +++ b/vlib/v/gen/c/auto_eq_methods.v @@ -220,11 +220,11 @@ fn (mut g Gen) gen_struct_equality_fn(left_type ast.Type) string { if field.typ.has_flag(.option) { left_arg_opt := g.read_opt_field(left_type, field_name, 'a', field.typ) right_arg_opt := g.read_opt_field(left_type, field_name, 'b', field.typ) - fn_builder.write_string('(((${left_arg_opt}).len == (${right_arg_opt}).len && (${left_arg_opt}).len == 0) || string__eq(${left_arg_opt}, ${right_arg_opt}))') + fn_builder.write_string('(((${left_arg_opt}).len == (${right_arg_opt}).len && (${left_arg_opt}).len == 0) || fast_string_eq(${left_arg_opt}, ${right_arg_opt}))') } else if field.typ.is_ptr() { - fn_builder.write_string('((${left_arg}->len == ${right_arg}->len && ${left_arg}->len == 0) || string__eq(*(${left_arg}), *(${right_arg})))') + fn_builder.write_string('((${left_arg}->len == ${right_arg}->len && ${left_arg}->len == 0) || fast_string_eq(*(${left_arg}), *(${right_arg})))') } else { - fn_builder.write_string('((${left_arg}.len == ${right_arg}.len && ${left_arg}.len == 0) || string__eq(${left_arg}, ${right_arg}))') + fn_builder.write_string('((${left_arg}.len == ${right_arg}.len && ${left_arg}.len == 0) || fast_string_eq(${left_arg}, ${right_arg}))') } } else if field_type.sym.kind == .sum_type && !field.typ.is_ptr() { eq_fn := g.gen_sumtype_equality_fn(field.typ) @@ -294,7 +294,7 @@ fn (mut g Gen) gen_alias_equality_fn(left_type ast.Type) string { if info.parent_type.has_flag(.option) { left_var = '*' + g.read_opt(info.parent_type, 'a') right_var = '*' + g.read_opt(info.parent_type, 'b') - fn_builder.writeln('\treturn ((${left_var}).len == (${right_var}).len && (${left_var}).len == 0) || string__eq(${left_var}, ${right_var});') + fn_builder.writeln('\treturn ((${left_var}).len == (${right_var}).len && (${left_var}).len == 0) || fast_string_eq(${left_var}, ${right_var});') } else { fn_builder.writeln('\treturn string__eq(a, b);') } diff --git a/vlib/v/gen/c/infix.v b/vlib/v/gen/c/infix.v index 2058af57340c4f..f215776cc7b82c 100644 --- a/vlib/v/gen/c/infix.v +++ b/vlib/v/gen/c/infix.v @@ -129,7 +129,8 @@ fn (mut g Gen) infix_expr_eq_op(node ast.InfixExpr) { g.gen_plain_infix_expr(node) } else if (left.typ.idx() == ast.string_type_idx || (!has_defined_eq_operator && left.unaliased.idx() == ast.string_type_idx)) && node.right is ast.StringLiteral - && (node.right.val == '' || (node.left is ast.Ident && node.left.or_expr.kind == .absent)) { + && (node.right.val == '' || (node.left is ast.SelectorExpr + || (node.left is ast.Ident && node.left.or_expr.kind == .absent))) { if node.right.val == '' { // `str == ''` -> `str.len == 0` optimization g.write('(') @@ -137,7 +138,7 @@ fn (mut g Gen) infix_expr_eq_op(node ast.InfixExpr) { g.write(')') arrow := if left.typ.is_ptr() { '->' } else { '.' } g.write('${arrow}len ${node.op} 0') - } else { + } else if node.left is ast.Ident { // vmemcmp(left, "str", sizeof("str")) optimization slit := cescape_nonascii(util.smart_quote(node.right.val, node.right.is_raw)) var := g.expr_string(node.left) @@ -147,6 +148,17 @@ fn (mut g Gen) infix_expr_eq_op(node ast.InfixExpr) { } else { g.write('_SLIT_NE(${var}${arrow}str, ${var}${arrow}len, "${slit}")') } + } else { + // fast_string_eq optimization for string selector comparison to literals + if node.op == .ne { + g.write('!fast_string_eq(') + } else { + g.write('fast_string_eq(') + } + g.expr(node.left) + g.write(', ') + g.expr(node.right) + g.write(')') } } else if has_defined_eq_operator { if node.op == .ne { @@ -636,8 +648,26 @@ fn (mut g Gen) infix_expr_in_optimization(left ast.Expr, right ast.ArrayInit) { match elem_sym.kind { .string, .alias, .sum_type, .map, .interface, .array, .struct { if elem_sym.kind == .string { - g.write('string__eq(') - if left.is_auto_deref_var() || (left is ast.Ident && left.info is ast.IdentVar + is_auto_deref_var := left.is_auto_deref_var() + if left is ast.Ident && left.or_expr.kind == .absent + && array_expr is ast.StringLiteral { + var := g.expr_string(left) + slit := cescape_nonascii(util.smart_quote(array_expr.val, array_expr.is_raw)) + if is_auto_deref_var || (left.info is ast.IdentVar + && g.table.sym(left.obj.typ).kind in [.interface, .sum_type]) { + g.write('_SLIT_EQ(${var}->str, ${var}->len, "${slit}")') + } else { + g.write('_SLIT_EQ(${var}.str, ${var}.len, "${slit}")') + } + unsafe { + goto end + } + } else if array_expr is ast.StringLiteral { + g.write('fast_string_eq(') + } else { + g.write('string__eq(') + } + if is_auto_deref_var || (left is ast.Ident && left.info is ast.IdentVar && g.table.sym(left.obj.typ).kind in [.interface, .sum_type]) { g.write('*') } @@ -668,6 +698,7 @@ fn (mut g Gen) infix_expr_in_optimization(left ast.Expr, right ast.ArrayInit) { g.expr(array_expr) } } + end: if i < right.exprs.len - 1 { g.write(' || ') } diff --git a/vlib/v/gen/c/match.v b/vlib/v/gen/c/match.v index 97b68385fc20ac..050cfd3d8b31e3 100644 --- a/vlib/v/gen/c/match.v +++ b/vlib/v/gen/c/match.v @@ -4,6 +4,7 @@ module c import v.ast +import v.util fn (mut g Gen) need_tmp_var_in_match(node ast.MatchExpr) bool { if node.is_expr && node.return_type != ast.void_type && node.return_type != 0 { @@ -491,10 +492,19 @@ fn (mut g Gen) match_expr_classic(node ast.MatchExpr, is_expr bool, cond_var str g.write(')') } .string { - ptr_str := if node.cond_type.is_ptr() { '*' } else { '' } - g.write('string__eq(${ptr_str}${cond_var}, ') - g.expr(expr) - g.write(')') + if expr is ast.StringLiteral { + slit := cescape_nonascii(util.smart_quote(expr.val, expr.is_raw)) + if node.cond_type.is_ptr() { + g.write('_SLIT_EQ(${cond_var}->str, ${cond_var}->len, "${slit}")') + } else { + g.write('_SLIT_EQ(${cond_var}.str, ${cond_var}.len, "${slit}")') + } + } else { + ptr_str := if node.cond_type.is_ptr() { '*' } else { '' } + g.write('fast_string_eq(${ptr_str}${cond_var}, ') + g.expr(expr) + g.write(')') + } } .struct { derefs_expr := '*'.repeat(g.get_expr_type(expr).nr_muls())