From 40db569014471deb5bd17860be00d6833387be79 Mon Sep 17 00:00:00 2001 From: Lewis Russell Date: Sat, 3 Jun 2023 11:06:10 +0100 Subject: [PATCH] perf(iter): make ListIter.totable more efficient (#23714) --- runtime/lua/vim/iter.lua | 36 ++++++++++++++++++++++++++---------- 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/runtime/lua/vim/iter.lua b/runtime/lua/vim/iter.lua index 56012e9b9f..0e98d0437e 100644 --- a/runtime/lua/vim/iter.lua +++ b/runtime/lua/vim/iter.lua @@ -66,7 +66,7 @@ end ---@class ListIter : Iter ---@field _table table Underlying table data ---@field _head number Index to the front of a table iterator ----@field _tail number Index to the end of a table iterator +---@field _tail number Index to the end of a table iterator (exclusive) local ListIter = {} ListIter.__index = setmetatable(ListIter, Iter) ListIter.__call = function(self) @@ -321,17 +321,33 @@ end ---@private function ListIter.totable(self) - if self._head == 1 and self._tail == #self._table + 1 and self.next == ListIter.next then - -- Sanitize packed table values - if getmetatable(self._table[1]) == packedmt then - for i = 1, #self._table do - self._table[i] = sanitize(self._table[i]) - end - end - return self._table + if self.next ~= ListIter.next or self._head >= self._tail then + return Iter.totable(self) end - return Iter.totable(self) + local needs_sanitize = getmetatable(self._table[1]) == packedmt + + -- Reindex and sanitize. + local len = self._tail - self._head + + if needs_sanitize then + for i = 1, len do + self._table[i] = sanitize(self._table[self._head - 1 + i]) + end + else + for i = 1, len do + self._table[i] = self._table[self._head - 1 + i] + end + end + + for i = len + 1, table.maxn(self._table) do + self._table[i] = nil + end + + self._head = 1 + self._tail = len + 1 + + return self._table end --- Fold an iterator or table into a single value.