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);
     }

Reply via email to