perf(api): reduce redundant win_find_tabpage calls (#35643)

Problem: `nvim_win_set_config` calls `win_find_tabpage(parent)` with redundant calls

Solution: Cache `parent_tp` early and reuse before window operations.
This commit is contained in:
glepnir
2025-09-06 19:48:44 +08:00
committed by GitHub
parent bc15b35cf6
commit 14e94f4617

View File

@@ -416,6 +416,8 @@ void nvim_win_set_config(Window window, Dict(win_config) *config, Error *err)
return; return;
} }
win_T *parent = config->win == 0 ? curwin : NULL; win_T *parent = config->win == 0 ? curwin : NULL;
tabpage_T *parent_tp = config->win == 0 ? curtab : NULL;
if (config->win > 0) { if (config->win > 0) {
parent = find_window_by_handle(fconfig.window, err); parent = find_window_by_handle(fconfig.window, err);
if (!parent) { if (!parent) {
@@ -424,13 +426,15 @@ void nvim_win_set_config(Window window, Dict(win_config) *config, Error *err)
api_set_error(err, kErrorTypeException, "Cannot split a floating window"); api_set_error(err, kErrorTypeException, "Cannot split a floating window");
return; return;
} }
parent_tp = win_find_tabpage(parent);
// Prevent autocmd window from being moved into another tabpage // Prevent autocmd window from being moved into another tabpage
if (is_aucmd_win(win) && win_find_tabpage(win) != win_find_tabpage(parent)) { if (is_aucmd_win(win) && win_tp != parent_tp) {
api_set_error(err, kErrorTypeException, "Cannot move autocmd win to another tabpage"); api_set_error(err, kErrorTypeException, "Cannot move autocmd win to another tabpage");
return; return;
} }
} }
if (was_split && !to_split) { if (was_split && !to_split) {
if (!win_new_float(win, false, fconfig, err)) { if (!win_new_float(win, false, fconfig, err)) {
return; return;
@@ -440,17 +444,9 @@ void nvim_win_set_config(Window window, Dict(win_config) *config, Error *err)
WinSplit old_split = win_split_dir(win); WinSplit old_split = win_split_dir(win);
if (has_vertical && !has_split) { if (has_vertical && !has_split) {
if (config->vertical) { if (config->vertical) {
if (old_split == kWinSplitRight || p_spr) { fconfig.split = (old_split == kWinSplitRight || p_spr) ? kWinSplitRight : kWinSplitLeft;
fconfig.split = kWinSplitRight;
} else {
fconfig.split = kWinSplitLeft;
}
} else { } else {
if (old_split == kWinSplitBelow || p_sb) { fconfig.split = (old_split == kWinSplitBelow || p_sb) ? kWinSplitBelow : kWinSplitAbove;
fconfig.split = kWinSplitBelow;
} else {
fconfig.split = kWinSplitAbove;
}
} }
} }
merge_win_config(&win->w_config, fconfig); merge_win_config(&win->w_config, fconfig);
@@ -473,8 +469,7 @@ void nvim_win_set_config(Window window, Dict(win_config) *config, Error *err)
return; // error already set return; // error already set
} }
// Can't move the cmdwin or its old curwin to a different tabpage. // Can't move the cmdwin or its old curwin to a different tabpage.
if ((win == cmdwin_win || win == cmdwin_old_curwin) && parent != NULL if ((win == cmdwin_win || win == cmdwin_old_curwin) && parent && parent_tp != win_tp) {
&& win_find_tabpage(parent) != win_tp) {
api_set_error(err, kErrorTypeException, "%s", e_cmdwin); api_set_error(err, kErrorTypeException, "%s", e_cmdwin);
return; return;
} }
@@ -482,8 +477,7 @@ void nvim_win_set_config(Window window, Dict(win_config) *config, Error *err)
bool to_split_ok = false; bool to_split_ok = false;
// If we are moving curwin to another tabpage, switch windows *before* we remove it from the // If we are moving curwin to another tabpage, switch windows *before* we remove it from the
// window list or remove its frame (if non-floating), so it's valid for autocommands. // window list or remove its frame (if non-floating), so it's valid for autocommands.
const bool curwin_moving_tp const bool curwin_moving_tp = win == curwin && parent && win_tp != parent_tp;
= win == curwin && parent != NULL && win_tp != win_find_tabpage(parent);
if (curwin_moving_tp) { if (curwin_moving_tp) {
if (was_split) { if (was_split) {
int dir; int dir;
@@ -583,7 +577,7 @@ void nvim_win_set_config(Window window, Dict(win_config) *config, Error *err)
} }
int flags = win_split_flags(fconfig.split, parent == NULL) | WSP_NOENTER; int flags = win_split_flags(fconfig.split, parent == NULL) | WSP_NOENTER;
tabpage_T *const parent_tp = parent ? win_find_tabpage(parent) : curtab; parent_tp = parent ? win_find_tabpage(parent) : curtab;
TRY_WRAP(err, { TRY_WRAP(err, {
const bool need_switch = parent != NULL && parent != curwin; const bool need_switch = parent != NULL && parent != curwin;