From cc7caf43846d4b55f72d4da65e403f741cb16486 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Thu, 9 Jan 2025 12:59:29 -0300 Subject: [PATCH] cgen: minor optimization removing repeated code (#23417) --- vlib/v/gen/c/cgen.v | 64 +++++++++++++++++++------------------ vlib/v/gen/c/spawn_and_go.v | 32 +++++++++---------- 2 files changed, 49 insertions(+), 47 deletions(-) diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 84e309a69c83d1..eb40fcbbffecad 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -5503,10 +5503,11 @@ fn (mut g Gen) return_stmt(node ast.Return) { g.inside_return = old_inside_return } - expr0 := if node.exprs.len > 0 { node.exprs[0] } else { ast.empty_expr } - type0 := if node.exprs.len > 0 { node.types[0] } else { ast.void_type } + exprs_len := node.exprs.len + expr0 := if exprs_len > 0 { node.exprs[0] } else { ast.empty_expr } + type0 := if exprs_len > 0 { node.types[0] } else { ast.void_type } - if node.exprs.len > 0 { + if exprs_len > 0 { // skip `return $vweb.html()` if expr0 is ast.ComptimeCall && expr0.is_vweb { g.inside_return_tmpl = true @@ -5516,10 +5517,11 @@ fn (mut g Gen) return_stmt(node ast.Return) { return } } + ret_type := g.fn_decl.return_type // got to do a correct check for multireturn - sym := g.table.sym(g.unwrap_generic(g.fn_decl.return_type)) - mut fn_ret_type := g.fn_decl.return_type + sym := g.table.sym(g.unwrap_generic(ret_type)) + mut fn_ret_type := ret_type if sym.kind == .alias { unaliased_type := g.table.unaliased_type(fn_ret_type) if unaliased_type.has_option_or_result() { @@ -5533,7 +5535,7 @@ fn (mut g Gen) return_stmt(node ast.Return) { fn_return_is_fixed_array_non_result := fn_return_is_fixed_array && !fn_ret_type.has_option_or_result() mut has_semicolon := false - if node.exprs.len == 0 { + if exprs_len == 0 { g.write_defer_stmts_when_needed() if fn_return_is_option || fn_return_is_result { styp := g.styp(fn_ret_type) @@ -5556,8 +5558,8 @@ fn (mut g Gen) return_stmt(node ast.Return) { ret_typ := g.ret_styp(g.unwrap_generic(fn_ret_type)) // `return fn_call_opt()` - if node.exprs.len == 1 && (fn_return_is_option || fn_return_is_result) && expr0 is ast.CallExpr - && expr0.return_type == g.fn_decl.return_type && expr0.or_block.kind == .absent { + if exprs_len == 1 && (fn_return_is_option || fn_return_is_result) && expr0 is ast.CallExpr + && expr0.return_type == ret_type && expr0.or_block.kind == .absent { if g.defer_stmts.len > 0 { g.write('${ret_typ} ${tmpvar} = ') g.expr(expr0) @@ -5574,7 +5576,7 @@ fn (mut g Gen) return_stmt(node ast.Return) { } mut use_tmp_var := g.defer_stmts.len > 0 || g.defer_profile_code.len > 0 || g.cur_lock.lockeds.len > 0 - || (fn_return_is_multi && node.exprs.len >= 1 && fn_return_is_option) + || (fn_return_is_multi && exprs_len >= 1 && fn_return_is_option) || fn_return_is_fixed_array_non_result || (fn_return_is_multi && node.types.any(g.table.final_sym(it).kind == .array_fixed)) // handle promoting none/error/function returning _option' @@ -5601,7 +5603,7 @@ fn (mut g Gen) return_stmt(node ast.Return) { g.writeln(';') if use_tmp_var { // handle options when returning `none` for `?(int, ?int)` - if fn_return_is_multi && node.exprs.len >= 1 { + if fn_return_is_multi && exprs_len >= 1 { mr_info := sym.info as ast.MultiReturn for i in 0 .. mr_info.types.len { if mr_info.types[i].has_flag(.option) { @@ -5646,8 +5648,8 @@ fn (mut g Gen) return_stmt(node ast.Return) { } } // regular cases - if fn_return_is_multi && node.exprs.len > 0 && !g.expr_is_multi_return_call(expr0) { - if node.exprs.len == 1 && (expr0 is ast.IfExpr || expr0 is ast.MatchExpr) { + if fn_return_is_multi && exprs_len > 0 && !g.expr_is_multi_return_call(expr0) { + if exprs_len == 1 && (expr0 is ast.IfExpr || expr0 is ast.MatchExpr) { // use a temporary for `return if cond { x,y } else { a,b }` or `return match expr { abc { x, y } else { z, w } }` g.write('${ret_typ} ${tmpvar} = ') g.expr(expr0) @@ -5660,11 +5662,11 @@ fn (mut g Gen) return_stmt(node ast.Return) { mut styp := '' if fn_return_is_option { g.writeln('${ret_typ} ${tmpvar};') - styp = g.base_type(g.fn_decl.return_type) + styp = g.base_type(ret_type) g.write('_option_ok(&(${styp}[]) { ') } else if fn_return_is_result { g.writeln('${ret_typ} ${tmpvar};') - styp = g.base_type(g.fn_decl.return_type) + styp = g.base_type(ret_type) g.write('_result_ok(&(${styp}[]) { ') } else { if use_tmp_var { @@ -5672,7 +5674,7 @@ fn (mut g Gen) return_stmt(node ast.Return) { } else { g.write('return ') } - styp = g.styp(g.fn_decl.return_type) + styp = g.styp(ret_type) } // Use this to keep the tmp assignments in order mut multi_unpack := '' @@ -5705,7 +5707,7 @@ fn (mut g Gen) return_stmt(node ast.Return) { expr_types := expr_sym.mr_info().types for j, _ in expr_types { g.write('.arg${arg_idx}=${tmp}.arg${j}') - if j < expr_types.len || i < node.exprs.len - 1 { + if j < expr_types.len || i < exprs_len - 1 { g.write(',') } arg_idx++ @@ -5733,7 +5735,7 @@ fn (mut g Gen) return_stmt(node ast.Return) { g.expr(expr) } } - if i < node.exprs.len - 1 { + if i < exprs_len - 1 { g.write(', ') } arg_idx++ @@ -5764,7 +5766,7 @@ fn (mut g Gen) return_stmt(node ast.Return) { g.writeln('return ${tmpvar};') has_semicolon = true } - } else if node.exprs.len >= 1 { + } else if exprs_len >= 1 { if node.types.len == 0 { g.checker_bug('node.exprs.len == ${node.exprs.len} && node.types.len == 0', node.pos) @@ -5904,26 +5906,26 @@ fn (mut g Gen) return_stmt(node ast.Return) { g.write('return ') } if expr0.is_auto_deref_var() && !fn_return_is_fixed_array { - if g.fn_decl.return_type.is_ptr() { + if ret_type.is_ptr() { var_str := g.expr_string(expr0) g.write(var_str.trim('&')) - } else if g.fn_decl.return_type.has_flag(.option) { - g.expr_with_opt(expr0, type0, g.fn_decl.return_type) - } else if g.table.sym(g.fn_decl.return_type).kind in [.sum_type, .interface] { - g.expr_with_cast(expr0, type0, g.fn_decl.return_type) + } else if ret_type.has_flag(.option) { + g.expr_with_opt(expr0, type0, ret_type) + } else if g.table.sym(ret_type).kind in [.sum_type, .interface] { + g.expr_with_cast(expr0, type0, ret_type) } else { g.write('*') g.expr(expr0) } } else { - if g.fn_decl.return_type.has_flag(.option) { + if ret_type.has_flag(.option) { expr0_is_alias_fn_ret := expr0 is ast.CallExpr && type0.has_flag(.option) && g.table.type_kind(type0) in [.placeholder, .alias] // return foo() where foo() returns different option alias than current fn if expr0_is_alias_fn_ret { - g.expr_opt_with_cast(expr0, type0, g.fn_decl.return_type) + g.expr_opt_with_cast(expr0, type0, ret_type) } else { - g.expr_with_opt(expr0, type0, g.fn_decl.return_type) + g.expr_with_opt(expr0, type0, ret_type) } } else { if fn_return_is_fixed_array && !type0.has_option_or_result() { @@ -5945,30 +5947,30 @@ fn (mut g Gen) return_stmt(node ast.Return) { if expr0 is ast.ArrayInit && expr0.is_fixed && expr0.has_init { if (expr0 as ast.ArrayInit).init_expr.is_literal() { g.write('{.ret_arr=') - g.expr_with_cast(expr0, type0, g.fn_decl.return_type) + g.expr_with_cast(expr0, type0, ret_type) g.writeln('};') } else { g.writeln('{0};') g.write('memcpy(${tmpvar}.ret_arr, ') - g.expr_with_cast(expr0, type0, g.fn_decl.return_type) + g.expr_with_cast(expr0, type0, ret_type) g.write(', sizeof(${g.styp(type0)}))') } } else { g.writeln('{0};') tmpvar2 := g.new_tmp_var() g.write('${g.styp(type0)} ${tmpvar2} = ') - g.expr_with_cast(expr0, type0, g.fn_decl.return_type) + g.expr_with_cast(expr0, type0, ret_type) g.writeln(';') g.write('memcpy(${tmpvar}.ret_arr, ${tmpvar2}, sizeof(${g.styp(type0)}))') } } else { g.writeln('{0};') g.write('memcpy(${tmpvar}.ret_arr, ') - g.expr_with_cast(expr0, type0, g.fn_decl.return_type) + g.expr_with_cast(expr0, type0, ret_type) g.write(', sizeof(${g.styp(type0)}))') } } else { - g.expr_with_cast(expr0, type0, g.fn_decl.return_type) + g.expr_with_cast(expr0, type0, ret_type) } } } diff --git a/vlib/v/gen/c/spawn_and_go.v b/vlib/v/gen/c/spawn_and_go.v index f16285eaba1135..d37f93d6373db0 100644 --- a/vlib/v/gen/c/spawn_and_go.v +++ b/vlib/v/gen/c/spawn_and_go.v @@ -118,14 +118,15 @@ fn (mut g Gen) spawn_and_go_expr(node ast.SpawnExpr, mode SpawnGoMode) { g.expr(arg.expr) g.writeln(';') } - s_ret_typ := g.styp(node.call_expr.return_type) - if g.pref.os == .windows && node.call_expr.return_type != ast.void_type { + call_ret_type := node.call_expr.return_type + s_ret_typ := g.styp(call_ret_type) + if g.pref.os == .windows && call_ret_type != ast.void_type { g.writeln('${arg_tmp_var}->ret_ptr = (void *) _v_malloc(sizeof(${s_ret_typ}));') } - is_opt := node.call_expr.return_type.has_flag(.option) - is_res := node.call_expr.return_type.has_flag(.result) + is_opt := call_ret_type.has_flag(.option) + is_res := call_ret_type.has_flag(.result) mut gohandle_name := '' - if node.call_expr.return_type == ast.void_type { + if call_ret_type == ast.void_type { if is_opt { gohandle_name = '__v_thread_Option_void' } else if is_res { @@ -134,13 +135,12 @@ fn (mut g Gen) spawn_and_go_expr(node ast.SpawnExpr, mode SpawnGoMode) { gohandle_name = '__v_thread' } } else { - ret_styp := g.styp(g.unwrap_generic(node.call_expr.return_type)).replace('*', - '_ptr') + ret_styp := g.styp(g.unwrap_generic(call_ret_type)).replace('*', '_ptr') gohandle_name = '__v_thread_${ret_styp}' } if is_spawn { if g.pref.os == .windows { - simple_handle := if node.is_expr && node.call_expr.return_type != ast.void_type { + simple_handle := if node.is_expr && call_ret_type != ast.void_type { 'thread_handle_${tmp}' } else { 'thread_${tmp}' @@ -148,7 +148,7 @@ fn (mut g Gen) spawn_and_go_expr(node ast.SpawnExpr, mode SpawnGoMode) { stack_size := g.get_cur_thread_stack_size(expr.name) g.writeln('HANDLE ${simple_handle} = CreateThread(0, ${stack_size}, (LPTHREAD_START_ROUTINE)${wrapper_fn_name}, ${arg_tmp_var}, 0, 0); // fn: ${expr.name}') g.writeln('if (!${simple_handle}) panic_lasterr(tos3("`go ${name}()`: "));') - if node.is_expr && node.call_expr.return_type != ast.void_type { + if node.is_expr && call_ret_type != ast.void_type { g.writeln('${gohandle_name} thread_${tmp} = {') g.writeln('\t.ret_ptr = ${arg_tmp_var}->ret_ptr,') g.writeln2('\t.handle = thread_handle_${tmp}', '};') @@ -195,12 +195,12 @@ fn (mut g Gen) spawn_and_go_expr(node ast.SpawnExpr, mode SpawnGoMode) { g.waiter_fn_definitions.writeln('${s_ret_typ} ${waiter_fn_name}(${gohandle_name} thread);') g.gowrappers.writeln('\n${s_ret_typ} ${waiter_fn_name}(${gohandle_name} thread) {') mut c_ret_ptr_ptr := 'NULL' - if node.call_expr.return_type != ast.void_type { + if call_ret_type != ast.void_type { g.gowrappers.writeln('\t${s_ret_typ}* ret_ptr;') c_ret_ptr_ptr = '&ret_ptr' } if g.pref.os == .windows { - if node.call_expr.return_type == ast.void_type { + if call_ret_type == ast.void_type { g.gowrappers.writeln('\tu32 stat = WaitForSingleObject(thread, INFINITE);') } else { g.gowrappers.writeln('\tu32 stat = WaitForSingleObject(thread.handle, INFINITE);') @@ -211,13 +211,13 @@ fn (mut g Gen) spawn_and_go_expr(node ast.SpawnExpr, mode SpawnGoMode) { } g.gowrappers.writeln('\tif (stat != 0) { _v_panic(_SLIT("unable to join thread")); }') if g.pref.os == .windows { - if node.call_expr.return_type == ast.void_type { + if call_ret_type == ast.void_type { g.gowrappers.writeln('\tCloseHandle(thread);') } else { g.gowrappers.writeln('\tCloseHandle(thread.handle);') } } - if node.call_expr.return_type != ast.void_type { + if call_ret_type != ast.void_type { g.gowrappers.writeln('\t${s_ret_typ} ret = *ret_ptr;') g.gowrappers.writeln('\t_v_free(ret_ptr);') g.gowrappers.writeln('\treturn ret;') @@ -288,7 +288,7 @@ fn (mut g Gen) spawn_and_go_expr(node ast.SpawnExpr, mode SpawnGoMode) { styp := g.styp(expr.receiver_type) g.type_definitions.writeln('\t${styp} arg0;') } - need_return_ptr := g.pref.os == .windows && node.call_expr.return_type != ast.void_type + need_return_ptr := g.pref.os == .windows && call_ret_type != ast.void_type for i, arg in expr.args { arg_sym := g.table.sym(arg.typ) if arg_sym.info is ast.FnType { @@ -307,7 +307,7 @@ fn (mut g Gen) spawn_and_go_expr(node ast.SpawnExpr, mode SpawnGoMode) { thread_ret_type := if g.pref.os == .windows { 'u32' } else { 'void*' } g.type_definitions.writeln('${g.static_modifier} ${thread_ret_type} ${wrapper_fn_name}(${wrapper_struct_name} *arg);') g.gowrappers.writeln('${thread_ret_type} ${wrapper_fn_name}(${wrapper_struct_name} *arg) {') - if node.call_expr.return_type != ast.void_type { + if call_ret_type != ast.void_type { if g.pref.os == .windows { g.gowrappers.write_string('\t*((${s_ret_typ}*)(arg->ret_ptr)) = ') } else { @@ -398,7 +398,7 @@ fn (mut g Gen) spawn_and_go_expr(node ast.SpawnExpr, mode SpawnGoMode) { if is_spawn { g.gowrappers.writeln('\t_v_free(arg);') } - if g.pref.os != .windows && node.call_expr.return_type != ast.void_type { + if g.pref.os != .windows && call_ret_type != ast.void_type { g.gowrappers.writeln('\treturn ret_ptr;') } else { g.gowrappers.writeln('\treturn 0;')