Skip to content

Commit

Permalink
gen: support non-string map equality and speed it up
Browse files Browse the repository at this point in the history
Avoid allocating keys array (which wasn't freed).
Don't clone keys (which weren't freed).
Check right key exists before getting left value.
Use fast_string_eq for string values.
  • Loading branch information
ntrel committed Jan 1, 2021
1 parent 40b8d9c commit 4681ba1
Show file tree
Hide file tree
Showing 2 changed files with 31 additions and 20 deletions.
3 changes: 3 additions & 0 deletions vlib/builtin/map_test.v
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
48 changes: 28 additions & 20 deletions vlib/v/gen/auto_eq_methods.v
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,10 @@ 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]);')
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;')
if value_sym.kind == .function {
func := value_sym.info as table.FnType
ret_styp := g.typ(func.func.return_type)
Expand All @@ -117,25 +118,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 value_sym.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}')
Expand Down

0 comments on commit 4681ba1

Please sign in to comment.