sw/inc/bparr.hxx | 5 ++++ sw/source/core/bastyp/bparr.cxx | 41 +++++++++++++++++++++++++++++++++++++++ sw/source/core/docnode/nodes.cxx | 8 ------- 3 files changed, 47 insertions(+), 7 deletions(-)
New commits: commit 284d80825ec7cf3c39af91959e4bf3d539b066f4 Author: Noel Grandin <noel.gran...@collabora.co.uk> AuthorDate: Wed Mar 20 14:43:44 2024 +0200 Commit: Noel Grandin <noel.gran...@collabora.co.uk> CommitDate: Fri Mar 22 08:00:40 2024 +0100 tdf#158556 speed up SwNodes::RemoveNode Change-Id: I49daf93793c67da6261081fce92e1fed1a71248b Reviewed-on: https://gerrit.libreoffice.org/c/core/+/165139 Tested-by: Jenkins Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk> diff --git a/sw/inc/bparr.hxx b/sw/inc/bparr.hxx index 9f3e17f8d140..4f831c8bab19 100644 --- a/sw/inc/bparr.hxx +++ b/sw/inc/bparr.hxx @@ -91,6 +91,11 @@ public: void Move( sal_Int32 from, sal_Int32 to ); void Replace( sal_Int32 pos, BigPtrEntry* p); + /** Speed up the complicated removal logic in SwNodes::RemoveNode. + Returns the entry before pNotTheOne. + */ + BigPtrEntry* ReplaceTheOneAfter( BigPtrEntry* pNotTheOne, BigPtrEntry* pNewEntry); + SW_DLLPUBLIC BigPtrEntry* operator[]( sal_Int32 ) const; }; diff --git a/sw/source/core/bastyp/bparr.cxx b/sw/source/core/bastyp/bparr.cxx index b99385bfd3dc..03e035c69621 100644 --- a/sw/source/core/bastyp/bparr.cxx +++ b/sw/source/core/bastyp/bparr.cxx @@ -397,6 +397,47 @@ void BigPtrArray::Replace( sal_Int32 idx, BigPtrEntry* pElem) p->mvData[ idx - p->nStart ] = pElem; } +/** Speed up the complicated removal logic in SwNodes::RemoveNode. + Replaces the node AFTER pNotTheOne. + Returns the entry BEFORE pNotTheOne. +*/ +BigPtrEntry* BigPtrArray::ReplaceTheOneAfter( BigPtrEntry* pNotTheOne, BigPtrEntry* pNewEntry) +{ + assert(pNotTheOne->m_pBlock->pBigArr == this); + BlockInfo* p = pNotTheOne->m_pBlock; + sal_uInt16 nOffset = pNotTheOne->m_nOffset; + + // if the next node is inside the current block + if (nOffset < p->nElem - 1) + { + ++nOffset; + p->mvData[nOffset] = pNewEntry; + pNewEntry->m_nOffset = nOffset; + pNewEntry->m_pBlock = p; + --nOffset; + } + else + { + // slow path + BigPtrArray::Replace( pNotTheOne->GetPos()+1, pNewEntry ); + } + + // if the previous node is inside the current block + if (nOffset != 0) + { + --nOffset; + return p->mvData[nOffset]; + } + else + { + // slow path + sal_Int32 nPrevPos = pNotTheOne->GetPos(); + if (nPrevPos == 0) + return nullptr; + return BigPtrArray::operator[]( nPrevPos - 1 ); + } +} + /** Compress the array */ sal_uInt16 BigPtrArray::Compress() { diff --git a/sw/source/core/docnode/nodes.cxx b/sw/source/core/docnode/nodes.cxx index 0e2a0bc95c5d..5f059f94c519 100644 --- a/sw/source/core/docnode/nodes.cxx +++ b/sw/source/core/docnode/nodes.cxx @@ -2413,14 +2413,8 @@ void SwNodes::RemoveNode( SwNodeOffset nDelPos, SwNodeOffset nSz, bool bDel ) delete pDel; // coverity[use_after_free : FALSE] - pPrev will be reassigned if there will be another iteration to the loop pDel = pPrev; - sal_uLong nPrevNdIdx = pPrev->GetPos(); BigPtrEntry* pTempEntry = &aTempEntries[sal_Int32(nCnt)]; - BigPtrArray::Replace( nPrevNdIdx+1, pTempEntry ); - if( nCnt ) - pPrev = BigPtrArray::operator []( nPrevNdIdx - 1 ); - // the accessed element can be a naked BigPtrEntry from - // aTempEntries, so the downcast to SwNode* in - // SwNodes::operator[] would be illegal (and unnecessary) + pPrev = ReplaceTheOneAfter(pPrev, pTempEntry); } nDelPos = SwNodeOffset(pDel->GetPos() + 1); }