Merge #9803 from janlazo/vim-8.0.0504

Benchmarked using RelWithDebInfo build and the `:Time` command from
https://github.com/tpope/vim-scriptease .

    :Time for i in range(0,99999)|call exists(':abbreviate')|endfor

- before (8698830cbd):   0.431 seconds
- after (63025a1d65): 0.345 seconds
- Vim 8.1.1005 : 0.361 seconds
This commit is contained in:
Justin M. Keyes 2019-03-28 21:48:50 +01:00 committed by GitHub
commit 33f99431dc
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 75 additions and 25 deletions

View File

@ -2263,8 +2263,11 @@ static char_u * do_one_cmd(char_u **cmdlinep,
need_rethrow = check_cstack = FALSE;
doend:
if (curwin->w_cursor.lnum == 0) /* can happen with zero line number */
// can happen with zero line number
if (curwin->w_cursor.lnum == 0) {
curwin->w_cursor.lnum = 1;
curwin->w_cursor.col = 0;
}
if (errormsg != NULL && *errormsg != NUL && !did_emsg) {
if (flags & DOCMD_VERBOSE) {
@ -2440,10 +2443,24 @@ static char_u *find_command(exarg_T *eap, int *full)
}
}
if (ASCII_ISLOWER(*eap->cmd))
eap->cmdidx = cmdidxs[CharOrdLow(*eap->cmd)];
else
eap->cmdidx = cmdidxs[26];
if (ASCII_ISLOWER(eap->cmd[0])) {
const int c1 = eap->cmd[0];
const int c2 = eap->cmd[1];
if (command_count != (int)CMD_SIZE) {
iemsg((char *)_("E943: Command table needs to be updated, run 'make'"));
getout(1);
}
// Use a precomputed index for fast look-up in cmdnames[]
// taking into account the first 2 letters of eap->cmd.
eap->cmdidx = cmdidxs1[CharOrdLow(c1)];
if (ASCII_ISLOWER(c2)) {
eap->cmdidx += cmdidxs2[CharOrdLow(c1)][CharOrdLow(c2)];
}
} else {
eap->cmdidx = CMD_bang;
}
for (; (int)eap->cmdidx < (int)CMD_SIZE;
eap->cmdidx = (cmdidx_T)((int)eap->cmdidx + 1))

View File

@ -28,34 +28,41 @@ local lastchar = nil
local i
local cmd
local first = true
local prevfirstchar = nil
local byte_a = string.byte('a')
local byte_z = string.byte('z')
local a_to_z = byte_z - byte_a + 1
local cmdidxs = string.format([[
static const cmdidx_T cmdidxs[%u] = {
]], byte_z - byte_a + 2)
-- Table giving the index of the first command in cmdnames[] to lookup
-- based on the first letter of a command.
local cmdidxs1_out = string.format([[
static const uint16_t cmdidxs1[%u] = {
]], a_to_z)
-- Table giving the index of the first command in cmdnames[] to lookup
-- based on the first 2 letters of a command.
-- Values in cmdidxs2[c1][c2] are relative to cmdidxs1[c1] so that they
-- fit in a byte.
local cmdidxs2_out = string.format([[
static const char_u cmdidxs2[%u][%u] = {
/* a b c d e f g h i j k l m n o p q r s t u v w x y z */
]], a_to_z, a_to_z)
enumfile:write([[
typedef enum CMD_index {
]])
defsfile:write(string.format([[
static const int command_count = %u;
]], #defs))
defsfile:write(string.format([[
static CommandDefinition cmdnames[%u] = {
]], #defs))
local cmds, cmdidxs1, cmdidxs2 = {}, {}, {}
for i, cmd in ipairs(defs) do
local enumname = cmd.enum or ('CMD_' .. cmd.command)
firstchar = string.byte(cmd.command)
if firstchar ~= prevfirstchar then
if (not prevfirstchar
or (byte_a <= firstchar and firstchar <= byte_z)
or (byte_a <= prevfirstchar and prevfirstchar <= byte_z)) then
if not first then
cmdidxs = cmdidxs .. ',\n'
end
cmdidxs = cmdidxs .. ' ' .. enumname
end
prevfirstchar = firstchar
local byte_cmd = cmd.command:sub(1, 1):byte()
if byte_a <= byte_cmd and byte_cmd <= byte_z then
table.insert(cmds, cmd.command)
end
if first then
first = false
@ -71,6 +78,35 @@ for i, cmd in ipairs(defs) do
.cmd_addr_type = %i
}]], enumname, cmd.command, cmd.func, cmd.flags, cmd.addr_type))
end
for i = #cmds, 1, -1 do
local cmd = cmds[i]
-- First and second characters of the command
local c1 = cmd:sub(1, 1)
cmdidxs1[c1] = i - 1
if cmd:len() >= 2 then
local c2 = cmd:sub(2, 2)
local byte_c2 = string.byte(c2)
if byte_a <= byte_c2 and byte_c2 <= byte_z then
if not cmdidxs2[c1] then
cmdidxs2[c1] = {}
end
cmdidxs2[c1][c2] = i - 1
end
end
end
for i = byte_a, byte_z do
local c1 = string.char(i)
cmdidxs1_out = cmdidxs1_out .. ' /* ' .. c1 .. ' */ ' .. cmdidxs1[c1] .. ',\n'
cmdidxs2_out = cmdidxs2_out .. ' /* ' .. c1 .. ' */ {'
for j = byte_a, byte_z do
local c2 = string.char(j)
cmdidxs2_out = cmdidxs2_out ..
((cmdidxs2[c1] and cmdidxs2[c1][c2])
and string.format('%3d', cmdidxs2[c1][c2] - cmdidxs1[c1])
or ' 0') .. ','
end
cmdidxs2_out = cmdidxs2_out .. ' },\n'
end
defsfile:write([[
};
@ -81,8 +117,5 @@ enumfile:write([[
CMD_USER_BUF = -2
} cmdidx_T;
]])
cmdidxs = cmdidxs .. [[
};
]]
defsfile:write(cmdidxs)
defsfile:write(cmdidxs1_out .. '};\n')
defsfile:write(cmdidxs2_out .. '};\n')