Skip to content

Commit 6b855c1

Browse files
committed
v2: transformer pending_stmts swap-with-fresh instead of clone+clear
Replaces `saved := t.pending_stmts.clone(); t.pending_stmts.clear()` with `saved := t.pending_stmts; t.pending_stmts = []ast.Stmt{}` across 19 sites in expr.v, for.v, and transformer.v. The original pattern allocated a deep copy on every save and again on every restore; the swap pattern transfers ownership without copying buffer contents.
1 parent 90c51ad commit 6b855c1

3 files changed

Lines changed: 60 additions & 67 deletions

File tree

vlib/v2/transformer/expr.v

Lines changed: 22 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -72,8 +72,7 @@ fn (mut t Transformer) transform_expr(expr ast.Expr) ast.Expr {
7272
&& t.is_string_expr(expr.expr.lhs) {
7373
inner = t.rename_substr_to_checked(inner)
7474
}
75-
is_native_backend := t.pref != unsafe { nil }
76-
&& t.is_native_be
75+
is_native_backend := t.pref != unsafe { nil } && t.is_native_be
7776
if is_native_backend {
7877
return ast.Expr(ast.PostfixExpr{
7978
op: expr.op
@@ -1128,15 +1127,15 @@ fn (mut t Transformer) transform_match_branch_stmts(stmts []ast.Stmt) []ast.Stmt
11281127
if stmts.len > 1 {
11291128
out << t.transform_stmts(stmts[..stmts.len - 1])
11301129
}
1131-
saved_pending := t.pending_stmts.clone()
1132-
t.pending_stmts.clear()
1130+
saved_pending := t.pending_stmts
1131+
t.pending_stmts = []ast.Stmt{}
11331132
saved_skip_if_value_lowering := t.skip_if_value_lowering
11341133
if last.expr is ast.IfExpr {
11351134
t.skip_if_value_lowering = true
11361135
}
11371136
transformed_expr := t.transform_expr(last.expr)
11381137
t.skip_if_value_lowering = saved_skip_if_value_lowering
1139-
final_pending := t.pending_stmts.clone()
1138+
final_pending := t.pending_stmts
11401139
t.pending_stmts = saved_pending
11411140
for stmt in final_pending {
11421141
out << stmt
@@ -1465,14 +1464,14 @@ fn (mut t Transformer) transform_if_expr(expr ast.IfExpr) ast.Expr {
14651464
// Transform inner condition with smartcast (if not already lowered).
14661465
// Expression expansions from the condition must run before the
14671466
// nested if, while the outer smartcast is active.
1468-
saved_rest_pending := t.pending_stmts.clone()
1469-
t.pending_stmts.clear()
1467+
saved_rest_pending := t.pending_stmts
1468+
t.pending_stmts = []ast.Stmt{}
14701469
transformed_rest := if inner_cond_lowered {
14711470
inner_tag_check
14721471
} else {
14731472
t.transform_expr(cond.rhs)
14741473
}
1475-
rest_pending := t.pending_stmts.clone()
1474+
rest_pending := t.pending_stmts
14761475
t.pending_stmts = saved_rest_pending
14771476
t.smartcast_stack = active_smartcast_stack.clone()
14781477
t.smartcast_expr_counts = active_smartcast_counts.clone()
@@ -1541,10 +1540,10 @@ fn (mut t Transformer) transform_if_expr(expr ast.IfExpr) ast.Expr {
15411540
// Push interface-aware smartcast context
15421541
t.push_smartcast_ctx(iface_ctx)
15431542
// Transform inner condition and body with smartcast
1544-
saved_rest_pending := t.pending_stmts.clone()
1545-
t.pending_stmts.clear()
1543+
saved_rest_pending := t.pending_stmts
1544+
t.pending_stmts = []ast.Stmt{}
15461545
transformed_rest_fallback := t.transform_expr(cond.rhs)
1547-
rest_pending := t.pending_stmts.clone()
1546+
rest_pending := t.pending_stmts
15481547
t.pending_stmts = saved_rest_pending
15491548
transformed_body_fallback := t.transform_stmts(expr.stmts)
15501549
// Pop smartcast
@@ -1998,18 +1997,18 @@ fn (mut t Transformer) transform_if_expr(expr ast.IfExpr) ast.Expr {
19981997
for s in expr.stmts {
19991998
new_stmts << s
20001999
}
2001-
saved_p := t.pending_stmts.clone()
2002-
t.pending_stmts.clear()
2000+
saved_p := t.pending_stmts
2001+
t.pending_stmts = []ast.Stmt{}
20032002
t_stmts := t.transform_stmts(new_stmts)
2004-
inner_p := t.pending_stmts.clone()
2003+
inner_p := t.pending_stmts
20052004
t.pending_stmts = saved_p
20062005
for ip in inner_p {
20072006
t.pending_stmts << ip
20082007
}
2009-
saved_p2 := t.pending_stmts.clone()
2010-
t.pending_stmts.clear()
2008+
saved_p2 := t.pending_stmts
2009+
t.pending_stmts = []ast.Stmt{}
20112010
t_else := t.transform_expr(expr.else_expr)
2012-
inner_p2 := t.pending_stmts.clone()
2011+
inner_p2 := t.pending_stmts
20132012
t.pending_stmts = saved_p2
20142013
for ip in inner_p2 {
20152014
t.pending_stmts << ip
@@ -2050,22 +2049,22 @@ fn (mut t Transformer) transform_if_expr(expr ast.IfExpr) ast.Expr {
20502049
// Save and restore pending_stmts around branch transformation to prevent
20512050
// outer pending_stmts (e.g., from earlier RHS if-expr lowering) from being
20522051
// flushed into the inner branch's transform_stmts.
2053-
saved_pending := t.pending_stmts.clone()
2054-
t.pending_stmts.clear()
2052+
saved_pending := t.pending_stmts
2053+
t.pending_stmts = []ast.Stmt{}
20552054
transformed_stmts := t.transform_stmts(expr.stmts)
20562055
// Merge any pending_stmts generated by the then-branch transform back into the outer context.
2057-
inner_pending_then := t.pending_stmts.clone()
2056+
inner_pending_then := t.pending_stmts
20582057
t.pending_stmts = saved_pending
20592058
for ip in inner_pending_then {
20602059
t.pending_stmts << ip
20612060
}
20622061
t.smartcast_stack = outer_smartcast_stack.clone()
20632062
t.smartcast_expr_counts = outer_smartcast_counts.clone()
2064-
saved_pending2 := t.pending_stmts.clone()
2065-
t.pending_stmts.clear()
2063+
saved_pending2 := t.pending_stmts
2064+
t.pending_stmts = []ast.Stmt{}
20662065
transformed_else := t.transform_expr(expr.else_expr)
20672066
// Merge any pending_stmts generated by the else-expr transform back into the outer context.
2068-
inner_pending := t.pending_stmts.clone()
2067+
inner_pending := t.pending_stmts
20692068
t.pending_stmts = saved_pending2
20702069
for ip in inner_pending {
20712070
t.pending_stmts << ip

vlib/v2/transformer/for.v

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,7 @@ fn (mut t Transformer) smartcast_map_iter_value_expr(iter_expr ast.Expr, map_typ
144144
return iter_expr
145145
}
146146
data_access := t.synth_selector(iter_expr, '_data', types.Type(types.voidptr_))
147-
is_native_backend := t.pref != unsafe { nil }
148-
&& t.is_native_be
147+
is_native_backend := t.pref != unsafe { nil } && t.is_native_be
149148
variant_access := if is_native_backend {
150149
data_access
151150
} else {
@@ -695,8 +694,8 @@ fn (mut t Transformer) transform_untyped_for_in(stmt ast.ForStmt, for_in ast.For
695694
if typ := iter_typ {
696695
t.register_synth_type(iter_pos, typ)
697696
}
698-
iter_pending := t.pending_stmts.clone()
699-
t.pending_stmts.clear()
697+
iter_pending := t.pending_stmts
698+
t.pending_stmts = []ast.Stmt{}
700699

701700
index_pos := t.next_synth_pos()
702701
if typ := t.get_expr_type(for_in.value) {
@@ -733,8 +732,8 @@ fn (mut t Transformer) transform_untyped_for_in(stmt ast.ForStmt, for_in ast.For
733732
new_stmts << value_assign
734733
transformed_body := t.transform_stmts(stmt.stmts)
735734
new_stmts << transformed_body
736-
body_pending := t.pending_stmts.clone()
737-
t.pending_stmts.clear()
735+
body_pending := t.pending_stmts
736+
t.pending_stmts = []ast.Stmt{}
738737
t.pending_stmts << iter_pending
739738
t.pending_stmts << body_pending
740739

@@ -843,8 +842,8 @@ fn (mut t Transformer) transform_array_for_in_with_value_type(stmt ast.ForStmt,
843842
iter_pos := t.next_synth_pos()
844843
transformed_expr := t.iter_value_expr(for_in.expr, t.transform_expr(for_in.expr), iter_pos,
845844
iter_type)
846-
iter_pending := t.pending_stmts.clone()
847-
t.pending_stmts.clear()
845+
iter_pending := t.pending_stmts
846+
t.pending_stmts = []ast.Stmt{}
848847

849848
index_pos := t.next_synth_pos()
850849
t.register_synth_type(index_pos, value_type)
@@ -894,8 +893,8 @@ fn (mut t Transformer) transform_array_for_in_with_value_type(stmt ast.ForStmt,
894893
t.generic_var_type_params.delete(value_name)
895894
}
896895
new_stmts << transformed_body
897-
body_pending := t.pending_stmts.clone()
898-
t.pending_stmts.clear()
896+
body_pending := t.pending_stmts
897+
t.pending_stmts = []ast.Stmt{}
899898
t.pending_stmts << iter_pending
900899
t.pending_stmts << body_pending
901900

vlib/v2/transformer/transformer.v

Lines changed: 29 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,8 @@ fn new_transformer_base(env &types.Environment, p &pref.Preferences) &Transforme
293293
smartcast_expr_counts: map[string]int{}
294294
monomorphize_enabled: os.getenv('V2_TRANSFORMER_MONOMORPH') != ''
295295
monomorphized_specs: map[string]bool{}
296-
is_native_be: p != unsafe { nil } && (p.backend == .arm64 || p.backend == .x64)
296+
is_native_be: p != unsafe { nil }
297+
&& (p.backend == .arm64 || p.backend == .x64)
297298
}
298299
return t
299300
}
@@ -2061,8 +2062,7 @@ fn (t &Transformer) expr_depends_on_runtime_const(mod string, expr ast.Expr) boo
20612062
}
20622063

20632064
fn (mut t Transformer) collect_runtime_const_inits(files []ast.File) {
2064-
is_native := t.pref != unsafe { nil }
2065-
&& (t.is_native_be || t.pref.backend == .c)
2065+
is_native := t.pref != unsafe { nil } && (t.is_native_be || t.pref.backend == .c)
20662066
t.runtime_const_inits_by_mod.clear()
20672067
t.runtime_const_modules.clear()
20682068
t.runtime_const_init_fn_name.clear()
@@ -2347,13 +2347,13 @@ fn (mut t Transformer) transform_expr_in_module(mod string, expr ast.Expr) ast.E
23472347
fn (mut t Transformer) runtime_const_init_fn_stmt(mod string, fn_name string, inits []RuntimeConstInit) ast.Stmt {
23482348
mut stmts := []ast.Stmt{cap: inits.len}
23492349
for item in inits {
2350-
saved_pending := t.pending_stmts.clone()
2351-
t.pending_stmts.clear()
2350+
saved_pending := t.pending_stmts
2351+
t.pending_stmts = []ast.Stmt{}
23522352
old_skip_if := t.skip_if_value_lowering
23532353
t.skip_if_value_lowering = true
23542354
transformed_expr := t.transform_expr_in_module(mod, item.expr)
23552355
t.skip_if_value_lowering = old_skip_if
2356-
generated_pending := t.pending_stmts.clone()
2356+
generated_pending := t.pending_stmts
23572357
t.pending_stmts = saved_pending
23582358
for pending_stmt in generated_pending {
23592359
stmts << pending_stmt
@@ -4285,10 +4285,10 @@ fn (mut t Transformer) transform_or_call_expr(call_expr ast.Expr) (ast.Expr, []a
42854285
if t.pref == unsafe { nil } || t.pref.backend != .cleanc {
42864286
return t.transform_expr(call_expr), []ast.Stmt{}
42874287
}
4288-
saved_pending := t.pending_stmts.clone()
4289-
t.pending_stmts.clear()
4288+
saved_pending := t.pending_stmts
4289+
t.pending_stmts = []ast.Stmt{}
42904290
transformed_call := t.transform_expr(call_expr)
4291-
call_pending := t.pending_stmts.clone()
4291+
call_pending := t.pending_stmts
42924292
t.pending_stmts = saved_pending
42934293
return transformed_call, call_pending
42944294
}
@@ -4393,8 +4393,7 @@ fn (mut t Transformer) expand_direct_or_expr_assign(stmt ast.AssignStmt, or_expr
43934393
}
43944394
}
43954395

4396-
if t.is_native_be
4397-
&& is_string_range_or {
4396+
if t.is_native_be && is_string_range_or {
43984397
// String ranges still need the native inline bounds-check path because the
43994398
// checker records them as `string` instead of `!string`.
44004399
idx_expr := call_expr as ast.IndexExpr
@@ -4640,10 +4639,10 @@ fn (mut t Transformer) gen_typed_temp_ident(typ types.Type) ast.Ident {
46404639
}
46414640

46424641
fn (mut t Transformer) transform_expr_with_captured_pending(expr ast.Expr) (ast.Expr, []ast.Stmt) {
4643-
saved_pending := t.pending_stmts.clone()
4644-
t.pending_stmts.clear()
4642+
saved_pending := t.pending_stmts
4643+
t.pending_stmts = []ast.Stmt{}
46454644
transformed := t.transform_expr(expr)
4646-
captured := t.pending_stmts.clone()
4645+
captured := t.pending_stmts
46474646
t.pending_stmts = saved_pending
46484647
return transformed, captured
46494648
}
@@ -4996,8 +4995,8 @@ fn (mut t Transformer) try_expand_filter_or_map_expr(expr ast.Expr) ?ast.Expr {
49964995
// Transform generated statements while lowering the synthetic loop with the
49974996
// array type already resolved above. Nested expression expansions inside the
49984997
// loop body stay scoped to that loop.
4999-
saved_pending := t.pending_stmts.clone()
5000-
t.pending_stmts.clear()
4998+
saved_pending := t.pending_stmts
4999+
t.pending_stmts = []ast.Stmt{}
50015000
mut generated_stmts := []ast.Stmt{cap: 2}
50025001
if has_cache_stmt {
50035002
generated_stmts << cache_stmt
@@ -5008,7 +5007,7 @@ fn (mut t Transformer) try_expand_filter_or_map_expr(expr ast.Expr) ?ast.Expr {
50085007
t.open_scope()
50095008
transformed_for := ast.Stmt(t.transform_array_for_in(raw_for_stmt, for_in_stmt, iter_type))
50105009
t.close_scope()
5011-
inner_pending := t.pending_stmts.clone()
5010+
inner_pending := t.pending_stmts
50125011
t.pending_stmts = saved_pending
50135012
t.pending_stmts << transformed_generated
50145013
t.pending_stmts << transformed_for
@@ -5120,8 +5119,8 @@ fn (mut t Transformer) expand_any_or_all_expr(method_name string, receiver_expr
51205119
}
51215120
stmts: loop_body
51225121
})
5123-
saved_pending := t.pending_stmts.clone()
5124-
t.pending_stmts.clear()
5122+
saved_pending := t.pending_stmts
5123+
t.pending_stmts = []ast.Stmt{}
51255124
transformed_init := t.transform_stmt(init_stmt)
51265125
transformed_for := t.transform_stmt(for_stmt)
51275126
t.pending_stmts = saved_pending
@@ -5202,8 +5201,8 @@ fn (mut t Transformer) expand_count_expr(receiver_expr ast.Expr, body_expr ast.E
52025201
}
52035202
stmts: loop_body
52045203
})
5205-
saved_pending := t.pending_stmts.clone()
5206-
t.pending_stmts.clear()
5204+
saved_pending := t.pending_stmts
5205+
t.pending_stmts = []ast.Stmt{}
52075206
transformed_init := t.transform_stmt(init_stmt)
52085207
transformed_for := t.transform_stmt(for_stmt)
52095208
t.pending_stmts = saved_pending
@@ -6088,15 +6087,15 @@ fn (mut t Transformer) try_expand_or_expr_stmt(stmt ast.ExprStmt) ?[]ast.Stmt {
60886087
// pending_stmts (e.g., lower_if_expr_value creates _if_tN). These must
60896088
// be placed AFTER the or-expr prefix_stmts (which define _or_tN used
60906089
// by the if condition), not before.
6091-
saved_pending := t.pending_stmts.clone()
6092-
t.pending_stmts.clear()
6090+
saved_pending := t.pending_stmts
6091+
t.pending_stmts = []ast.Stmt{}
60936092
// The expression is used at statement level (ExprStmt), so skip
60946093
// IfExpr value lowering which would create temp variables for void results.
60956094
saved_skip_if := t.skip_if_value_lowering
60966095
t.skip_if_value_lowering = true
60976096
transformed_new := t.transform_expr(new_expr)
60986097
t.skip_if_value_lowering = saved_skip_if
6099-
inner_pending := t.pending_stmts.clone()
6098+
inner_pending := t.pending_stmts
61006099
t.pending_stmts = saved_pending
61016100
// Merge: prefix_stmts first (or-expr decls), then any inner pending
61026101
for ip in inner_pending {
@@ -6756,8 +6755,7 @@ fn (mut t Transformer) expand_single_or_expr(or_expr ast.OrExpr, mut prefix_stmt
67566755
is_result = true
67576756
}
67586757

6759-
if t.is_native_be
6760-
&& is_string_range_or {
6758+
if t.is_native_be && is_string_range_or {
67616759
idx_expr := call_expr as ast.IndexExpr
67626760
return t.expand_string_range_or_native_expr(idx_expr, or_expr.stmts, mut prefix_stmts)
67636761
}
@@ -9244,8 +9242,8 @@ fn (mut t Transformer) lower_assoc_expr(node ast.AssocExpr, take_addr bool) ast.
92449242
// Save pending_stmts from outer context to prevent field value transforms
92459243
// (which may call transform_stmts internally, e.g., for if-expression branches)
92469244
// from draining our accumulated stmts into the wrong scope.
9247-
saved_pending := t.pending_stmts.clone()
9248-
t.pending_stmts.clear()
9245+
saved_pending := t.pending_stmts
9246+
t.pending_stmts = []ast.Stmt{}
92499247
mut assoc_stmts := []ast.Stmt{cap: 1 + node.fields.len * 2}
92509248
assoc_stmts << ast.Stmt(ast.AssignStmt{
92519249
op: .decl_assign
@@ -10150,8 +10148,7 @@ fn (mut t Transformer) apply_smartcast_direct_ctx(original_expr ast.Expr, ctx Sm
1015010148
// For native backends (arm64/x64): _data is a plain i64 (void pointer) in the SSA struct.
1015110149
// No union variant sub-field exists, so just use _data directly.
1015210150
// For C backends: _data is a union, so access _data._variant for the specific member.
10153-
is_native_backend := t.pref != unsafe { nil }
10154-
&& t.is_native_be
10151+
is_native_backend := t.pref != unsafe { nil } && t.is_native_be
1015510152
data_access := t.synth_selector(transformed_base, '_data', types.Type(types.voidptr_))
1015610153
variant_access := if is_native_backend {
1015710154
data_access
@@ -10262,8 +10259,7 @@ fn (mut t Transformer) apply_smartcast_receiver_ctx(sumtype_expr ast.Expr, ctx S
1026210259
// Create data access.
1026310260
// For native backends: _data is a plain i64, no union variant sub-field.
1026410261
// For C backends: _data is a union, access _data._variant.
10265-
is_native_backend2 := t.pref != unsafe { nil }
10266-
&& t.is_native_be
10262+
is_native_backend2 := t.pref != unsafe { nil } && t.is_native_be
1026710263
data_access := t.synth_selector(transformed_base, '_data', types.Type(types.voidptr_))
1026810264
variant_access := if is_native_backend2 {
1026910265
data_access
@@ -12974,8 +12970,7 @@ fn (mut t Transformer) generate_fixed_array_str_fn(fn_name string) ast.Stmt {
1297412970
}
1297512971

1297612972
// Create parameter: a Array_fixed_T_N
12977-
param_type := if t.pref != unsafe { nil }
12978-
&& t.is_native_be {
12973+
param_type := if t.pref != unsafe { nil } && t.is_native_be {
1297912974
ast.Expr(ast.PrefixExpr{
1298012975
op: .amp
1298112976
expr: ast.Ident{

0 commit comments

Comments
 (0)