From 0a069dee799354587b153878d7587dbb8f4a3bc8 Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Fri, 1 Jan 2021 19:54:49 +0000 Subject: [PATCH] gen: support non-string map equality and speed it up (#7682) --- vlib/builtin/map_test.v | 3 ++ vlib/v/gen/auto_eq_methods.v | 53 +++++++++++++++++++++--------------- 2 files changed, 34 insertions(+), 22 deletions(-) diff --git a/vlib/builtin/map_test.v b/vlib/builtin/map_test.v index 7bc77e9239..881f2c87fc 100644 --- a/vlib/builtin/map_test.v +++ b/vlib/builtin/map_test.v @@ -487,7 +487,10 @@ fn test_int_keys() { assert m[5] == 25 m2 := {3:9 4:16 5:25} assert m2.len == 3 + // clone mc := m.clone() + same := mc == m + assert same assert mc.len == 3 mut all := []int{} for k, v in mc { diff --git a/vlib/v/gen/auto_eq_methods.v b/vlib/v/gen/auto_eq_methods.v index a19b37d1ac..f8e95759a3 100644 --- a/vlib/v/gen/auto_eq_methods.v +++ b/vlib/v/gen/auto_eq_methods.v @@ -94,7 +94,6 @@ fn (mut g Gen) gen_map_equality_fn(left table.Type) string { g.map_fn_definitions << ptr_typ left_sym := g.table.get_type_symbol(left) value_typ := left_sym.map_info().value_type - value_sym := g.table.get_type_symbol(value_typ) ptr_value_typ := g.typ(value_typ) g.type_definitions.writeln('static bool ${ptr_typ}_map_eq($ptr_typ a, $ptr_typ b); // auto') mut fn_builder := strings.new_builder(512) @@ -102,10 +101,13 @@ fn (mut g Gen) gen_map_equality_fn(left table.Type) string { fn_builder.writeln('\tif (a.len != b.len) {') fn_builder.writeln('\t\treturn false;') fn_builder.writeln('\t}') - fn_builder.writeln('\tarray_string _keys = map_keys(&a);') - fn_builder.writeln('\tfor (int i = 0; i < _keys.len; ++i) {') - fn_builder.writeln('\t\tstring k = string_clone( ((string*)_keys.data)[i]);') - if value_sym.kind == .function { + fn_builder.writeln('\tfor (int i = 0; i < a.key_values.len; ++i) {') + fn_builder.writeln('\t\tif (!DenseArray_has_index(&a.key_values, i)) continue;') + fn_builder.writeln('\t\tvoidptr k = DenseArray_key(&a.key_values, i);') + fn_builder.writeln('\t\tif (!map_exists_1(&b, k)) return false;') + kind := g.table.type_kind(value_typ) + if kind == .function { + value_sym := g.table.get_type_symbol(value_typ) func := value_sym.info as table.FnType ret_styp := g.typ(func.func.return_type) fn_builder.write('\t\t$ret_styp (*v) (') @@ -117,25 +119,32 @@ fn (mut g Gen) gen_map_equality_fn(left table.Type) string { fn_builder.write(', ') } } - fn_builder.writeln(') = (*(voidptr*)map_get_1(&a, &k, &(voidptr[]){ 0 }));') + fn_builder.writeln(') = *(voidptr*)map_get_1(&a, k, &(voidptr[]){ 0 });') } else { - fn_builder.writeln('\t\t$ptr_value_typ v = (*($ptr_value_typ*)map_get_1(&a, &k, &($ptr_value_typ[]){ 0 }));') + fn_builder.writeln('\t\t$ptr_value_typ v = *($ptr_value_typ*)map_get_1(&a, k, &($ptr_value_typ[]){ 0 });') } - if value_sym.kind == .string { - fn_builder.writeln('\t\tif (!map_exists_1(&b, &k) || string_ne((*(string*)map_get_1(&b, &k, &(string[]){_SLIT("")})), v)) {') - } else if value_sym.kind == .struct_ && !value_typ.is_ptr() { - eq_fn := g.gen_struct_equality_fn(value_typ) - fn_builder.writeln('\t\tif (!map_exists_1(&b, &k) || !${eq_fn}_struct_eq(*($ptr_value_typ*)map_get_1(&b, &k, &($ptr_value_typ[]){ 0 }), v)) {') - } else if value_sym.kind == .array && !value_typ.is_ptr() { - eq_fn := g.gen_array_equality_fn(value_typ) - fn_builder.writeln('\t\tif (!map_exists_1(&b, &k) || !${eq_fn}_arr_eq(*($ptr_value_typ*)map_get_1(&b, &k, &($ptr_value_typ[]){ 0 }), v)) {') - } else if value_sym.kind == .map && !value_typ.is_ptr() { - eq_fn := g.gen_map_equality_fn(value_typ) - fn_builder.writeln('\t\tif (!map_exists_1(&b, &k) || !${eq_fn}_map_eq(*($ptr_value_typ*)map_get_1(&b, &k, &($ptr_value_typ[]){ 0 }), v)) {') - } else if value_sym.kind == .function { - fn_builder.writeln('\t\tif (!map_exists_1(&b, &k) || (*(voidptr*)map_get_1(&b, &k, &(voidptr[]){ 0 })) != v) {') - } else { - fn_builder.writeln('\t\tif (!map_exists_1(&b, &k) || (*($ptr_value_typ*)map_get_1(&b, &k, &($ptr_value_typ[]){ 0 })) != v) {') + match kind { + .string { + fn_builder.writeln('\t\tif (!fast_string_eq(*(string*)map_get_1(&b, k, &(string[]){_SLIT("")}), v)) {') + } + .struct_ { + eq_fn := g.gen_struct_equality_fn(value_typ) + fn_builder.writeln('\t\tif (!${eq_fn}_struct_eq(*($ptr_value_typ*)map_get_1(&b, k, &($ptr_value_typ[]){ 0 }), v)) {') + } + .array { + eq_fn := g.gen_array_equality_fn(value_typ) + fn_builder.writeln('\t\tif (!${eq_fn}_arr_eq(*($ptr_value_typ*)map_get_1(&b, k, &($ptr_value_typ[]){ 0 }), v)) {') + } + .map { + eq_fn := g.gen_map_equality_fn(value_typ) + fn_builder.writeln('\t\tif (!${eq_fn}_map_eq(*($ptr_value_typ*)map_get_1(&b, k, &($ptr_value_typ[]){ 0 }), v)) {') + } + .function { + fn_builder.writeln('\t\tif (*(voidptr*)map_get_1(&b, k, &(voidptr[]){ 0 }) != v) {') + } + else { + fn_builder.writeln('\t\tif (*($ptr_value_typ*)map_get_1(&b, k, &($ptr_value_typ[]){ 0 }) != v) {') + } } fn_builder.writeln('\t\t\treturn false;') fn_builder.writeln('\t\t}')