Skip to content

Commit eb44844

Browse files
authored
cgen: optimize .map(), .any(), .filter() and .all() when using closure (#21256)
1 parent 1a35a78 commit eb44844

File tree

2 files changed

+104
-17
lines changed

2 files changed

+104
-17
lines changed

vlib/v/gen/c/array.v

Lines changed: 64 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -463,15 +463,23 @@ fn (mut g Gen) array_init_with_fields(node ast.ArrayInit, elem_type Type, is_amp
463463
}
464464
}
465465

466-
fn (mut g Gen) write_closure_fn(mut expr ast.AnonFn, var_name string) {
467-
past := g.past_tmp_var_new()
468-
fn_ptr_name := g.fn_var_signature(expr.decl.return_type, expr.decl.params.map(it.typ),
469-
past.tmp_var)
470-
g.write('${fn_ptr_name} = ')
466+
fn (mut g Gen) declare_closure_fn(mut expr ast.AnonFn, var_name string) {
467+
decl_var := g.fn_var_signature(expr.decl.return_type, expr.decl.params.map(it.typ),
468+
var_name)
469+
g.write('${decl_var} = ')
471470
g.gen_anon_fn(mut expr)
472471
g.writeln(';')
473-
g.past_tmp_var_done(past)
474-
g.write('(${var_name})') // usually `it`
472+
}
473+
474+
fn (mut g Gen) write_closure_fn(mut expr ast.AnonFn, var_name string, declared_var string) {
475+
if declared_var == '' {
476+
past := g.past_tmp_var_new()
477+
g.declare_closure_fn(mut expr, past.var_name)
478+
g.past_tmp_var_done(past)
479+
g.write('(${var_name})') // usually `it`
480+
} else {
481+
g.write('${declared_var}(${var_name})')
482+
}
475483
}
476484

477485
// `nums.map(it % 2 == 0)`
@@ -515,6 +523,15 @@ fn (mut g Gen) gen_array_map(node ast.CallExpr) {
515523
has_infix_left_var_name := g.write_prepared_tmp_value(past.tmp_var, node, ret_typ,
516524
'{0}')
517525
g.writeln('${past.tmp_var} = __new_array${noscan}(0, ${past.tmp_var}_len, sizeof(${ret_elem_type}));\n')
526+
527+
mut closure_var := ''
528+
if mut expr is ast.AnonFn {
529+
if expr.inherited_vars.len > 0 {
530+
closure_var = g.new_tmp_var()
531+
g.declare_closure_fn(mut expr, closure_var)
532+
}
533+
}
534+
518535
i := g.new_tmp_var()
519536
g.writeln('for (int ${i} = 0; ${i} < ${past.tmp_var}_len; ++${i}) {')
520537
g.indent++
@@ -526,7 +543,7 @@ fn (mut g Gen) gen_array_map(node ast.CallExpr) {
526543
ast.AnonFn {
527544
g.write('${ret_elem_type} ${tmp_map_expr_result_name} = ')
528545
if expr.inherited_vars.len > 0 {
529-
g.write_closure_fn(mut expr, var_name)
546+
g.write_closure_fn(mut expr, var_name, closure_var)
530547
} else {
531548
g.gen_anon_fn_decl(mut expr)
532549
g.write('${expr.decl.name}(${var_name})')
@@ -769,19 +786,29 @@ fn (mut g Gen) gen_array_filter(node ast.CallExpr) {
769786
noscan := g.check_noscan(info.elem_type)
770787
has_infix_left_var_name := g.write_prepared_tmp_value(past.tmp_var, node, styp, '{0}')
771788
g.writeln('${past.tmp_var} = __new_array${noscan}(0, ${past.tmp_var}_len, sizeof(${elem_type_str}));\n')
789+
790+
mut expr := node.args[0].expr
791+
var_name := g.get_array_expr_param_name(mut expr)
792+
793+
mut closure_var := ''
794+
if mut expr is ast.AnonFn {
795+
if expr.inherited_vars.len > 0 {
796+
closure_var = g.new_tmp_var()
797+
g.declare_closure_fn(mut expr, closure_var)
798+
}
799+
}
800+
772801
i := g.new_tmp_var()
773802
g.writeln('for (int ${i} = 0; ${i} < ${past.tmp_var}_len; ++${i}) {')
774803
g.indent++
775-
mut expr := node.args[0].expr
776-
var_name := g.get_array_expr_param_name(mut expr)
777804
g.write_prepared_var(var_name, info, elem_type_str, past.tmp_var, i)
778805
g.set_current_pos_as_last_stmt_pos()
779806
mut is_embed_map_filter := false
780807
match mut expr {
781808
ast.AnonFn {
782809
g.write('if (')
783810
if expr.inherited_vars.len > 0 {
784-
g.write_closure_fn(mut expr, var_name)
811+
g.write_closure_fn(mut expr, var_name, closure_var)
785812
} else {
786813
g.gen_anon_fn_decl(mut expr)
787814
g.write('${expr.decl.name}(${var_name})')
@@ -1163,19 +1190,29 @@ fn (mut g Gen) gen_array_any(node ast.CallExpr) {
11631190
elem_type_str := g.typ(info.elem_type)
11641191
has_infix_left_var_name := g.write_prepared_tmp_value(past.tmp_var, node, 'bool',
11651192
'false')
1193+
1194+
mut expr := node.args[0].expr
1195+
var_name := g.get_array_expr_param_name(mut expr)
1196+
1197+
mut closure_var := ''
1198+
if mut expr is ast.AnonFn {
1199+
if expr.inherited_vars.len > 0 {
1200+
closure_var = g.new_tmp_var()
1201+
g.declare_closure_fn(mut expr, closure_var)
1202+
}
1203+
}
11661204
i := g.new_tmp_var()
11671205
g.writeln('for (int ${i} = 0; ${i} < ${past.tmp_var}_len; ++${i}) {')
11681206
g.indent++
1169-
mut expr := node.args[0].expr
1170-
var_name := g.get_array_expr_param_name(mut expr)
1207+
11711208
g.write_prepared_var(var_name, info, elem_type_str, past.tmp_var, i)
11721209
g.set_current_pos_as_last_stmt_pos()
11731210
mut is_embed_map_filter := false
11741211
match mut expr {
11751212
ast.AnonFn {
11761213
g.write('if (')
11771214
if expr.inherited_vars.len > 0 {
1178-
g.write_closure_fn(mut expr, var_name)
1215+
g.write_closure_fn(mut expr, var_name, closure_var)
11791216
} else {
11801217
g.gen_anon_fn_decl(mut expr)
11811218
g.write('${expr.decl.name}(${var_name})')
@@ -1244,10 +1281,20 @@ fn (mut g Gen) gen_array_all(node ast.CallExpr) {
12441281
has_infix_left_var_name := g.write_prepared_tmp_value(past.tmp_var, node, 'bool',
12451282
'true')
12461283
i := g.new_tmp_var()
1247-
g.writeln('for (int ${i} = 0; ${i} < ${past.tmp_var}_len; ++${i}) {')
1248-
g.indent++
1284+
12491285
mut expr := node.args[0].expr
12501286
var_name := g.get_array_expr_param_name(mut expr)
1287+
1288+
mut closure_var := ''
1289+
if mut expr is ast.AnonFn {
1290+
if expr.inherited_vars.len > 0 {
1291+
closure_var = g.new_tmp_var()
1292+
g.declare_closure_fn(mut expr, closure_var)
1293+
}
1294+
}
1295+
1296+
g.writeln('for (int ${i} = 0; ${i} < ${past.tmp_var}_len; ++${i}) {')
1297+
g.indent++
12511298
g.write_prepared_var(var_name, info, elem_type_str, past.tmp_var, i)
12521299
g.empty_line = true
12531300
g.set_current_pos_as_last_stmt_pos()
@@ -1256,7 +1303,7 @@ fn (mut g Gen) gen_array_all(node ast.CallExpr) {
12561303
ast.AnonFn {
12571304
g.write('if (!(')
12581305
if expr.inherited_vars.len > 0 {
1259-
g.write_closure_fn(mut expr, var_name)
1306+
g.write_closure_fn(mut expr, var_name, closure_var)
12601307
} else {
12611308
g.gen_anon_fn_decl(mut expr)
12621309
g.write('${expr.decl.name}(${var_name})')
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
fn setup(fname string) (int, int, []int) {
2+
println(fname)
3+
return C._closure_cap, 42, []int{len: 5, init: index * 5}
4+
}
5+
6+
fn test_array_filter() {
7+
start_closure_cap, x, a := setup(@LOCATION)
8+
println(a.filter(fn [x] (i int) bool {
9+
println('x: ${x} | i: ${i}')
10+
return i < 20
11+
}))
12+
assert start_closure_cap - C._closure_cap == 1
13+
}
14+
15+
fn test_array_map() {
16+
start_closure_cap, x, a := setup(@LOCATION)
17+
println(a.map(fn [x] (i int) int {
18+
println('x: ${x} | i: ${i}')
19+
return x + i
20+
}))
21+
assert start_closure_cap - C._closure_cap == 1
22+
}
23+
24+
fn test_array_any() {
25+
start_closure_cap, x, a := setup(@LOCATION)
26+
println(a.any(fn [x] (i int) bool {
27+
println('x: ${x} | i: ${i}')
28+
return i < x
29+
}))
30+
assert start_closure_cap - C._closure_cap == 1
31+
}
32+
33+
fn test_array_all() {
34+
start_closure_cap, x, a := setup(@LOCATION)
35+
println(a.all(fn [x] (i int) bool {
36+
println('x: ${x} | i: ${i}')
37+
return i < x
38+
}))
39+
assert start_closure_cap - C._closure_cap == 1
40+
}

0 commit comments

Comments
 (0)