sw/source/core/bastyp/swcache.cxx |   10 ++++++++++
 sw/source/core/inc/swcache.hxx    |   10 ++++------
 sw/source/core/text/txtcache.cxx  |   36 ++++++++++++++++++++++++++++++++++++
 sw/source/core/text/txtfrm.cxx    |    4 ++++
 sw/source/core/view/viewsh.cxx    |   10 ++++------
 5 files changed, 58 insertions(+), 12 deletions(-)

New commits:
commit 16b7f46a40c194398d0b1ca39afc619f419ccb4f
Author:     Michael Stahl <michael.st...@cib.de>
AuthorDate: Mon Apr 29 17:21:18 2019 +0200
Commit:     Michael Stahl <michael.st...@cib.de>
CommitDate: Tue Apr 30 15:34:04 2019 +0200

    tdf#122607 sw: fix preservation of text frame cache entries
    
    SwSaveSetLRUOfst would leave only 50 cache entries available for the
    CalcLayout() to use; apparently it's not enough for this document.
    
    The difference between the 1st loading/layout and the 3rd loading/layout
    of the document is that in many paragraphs the cache entry is missing,
    because the entires of the previous loads were clogging up the cache
    and were preserved here, and the cache only has 50 available entries;
    if enough entries are available, everything is positioned properly.
    
    The idea with the 100 entries per visible shell actually comes from the
    CVS initial import, where there was a comment suggesting that; but the
    corresponding parameter was actually unused and removed in
    7c704c78d3c652504c064b4ac7af55a2c1ee49bb.
    
    Ideally we'd have time to investigate why a missing cache entry causes
    the wrong position...
    
    Reviewed-on: https://gerrit.libreoffice.org/71542
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@cib.de>
    (cherry picked from commit 3d37463eec0c891243a8971a34903b2da01c9e24)
    
    Change-Id: I64a72a94361dbf5717bbc709fa3bc9abbe18a37c

diff --git a/sw/source/core/bastyp/swcache.cxx 
b/sw/source/core/bastyp/swcache.cxx
index ab82fe11ba74..e90f89b87612 100644
--- a/sw/source/core/bastyp/swcache.cxx
+++ b/sw/source/core/bastyp/swcache.cxx
@@ -440,6 +440,7 @@ bool SwCache::Insert( SwCacheObj *pNew )
 
 void SwCache::SetLRUOfst( const sal_uInt16 nOfst )
 {
+    assert(nOfst < m_nCurMax);
     if ( !m_pRealFirst || ((m_aCacheObjects.size() - m_aFreePositions.size()) 
< nOfst) )
         return;
 
diff --git a/sw/source/core/inc/swcache.hxx b/sw/source/core/inc/swcache.hxx
index a481bbff28ff..2cc6138cb2b1 100644
--- a/sw/source/core/inc/swcache.hxx
+++ b/sw/source/core/inc/swcache.hxx
@@ -117,15 +117,12 @@ public:
     sal_uInt16 size() { return m_aCacheObjects.size(); }
 };
 
-/// Safely manipulate the cache
+/// Try to prevent visible SwParaPortions from being deleted.
 class SwSaveSetLRUOfst
 {
-    SwCache &rCache;
 public:
-    SwSaveSetLRUOfst( SwCache &rC, const sal_uInt16 nOfst )
-        : rCache( rC )          { rCache.SetLRUOfst( nOfst );  }
-
-    ~SwSaveSetLRUOfst()         { rCache.ResetLRUOfst(); }
+    SwSaveSetLRUOfst();
+    ~SwSaveSetLRUOfst();
 };
 
 /**
diff --git a/sw/source/core/text/txtcache.cxx b/sw/source/core/text/txtcache.cxx
index b2f412b07c5b..20b992d9e275 100644
--- a/sw/source/core/text/txtcache.cxx
+++ b/sw/source/core/text/txtcache.cxx
@@ -21,6 +21,9 @@
 #include <txtfrm.hxx>
 #include "porlay.hxx"
 
+#include <sfx2/viewsh.hxx>
+#include <view.hxx>
+
 SwTextLine::SwTextLine( SwTextFrame const *pFrame, SwParaPortion *pNew ) :
     SwCacheObj( static_cast<void const *>(pFrame) ),
     pLine( pNew )
@@ -135,4 +138,37 @@ void SwTextFrame::SetPara( SwParaPortion *pNew, bool 
bDelete )
     }
 }
 
+/** Prevent the SwParaPortions of the *visible* paragraphs from being deleted;
+    they would just be recreated on the next paint.
+
+    Heuristic: 100 per view are visible
+
+    If the cache is too small, enlarge it to ensure there are sufficient free
+    entries for the layout so it doesn't have to throw away a node's
+    SwParaPortion when it starts formatting the next node.
+*/
+SwSaveSetLRUOfst::SwSaveSetLRUOfst()
+{
+    sal_uInt16 nVisibleShells(0);
+    for (auto pView = SfxViewShell::GetFirst(true, checkSfxViewShell<SwView>);
+         pView != nullptr;
+         pView = SfxViewShell::GetNext(*pView, true, 
checkSfxViewShell<SwView>))
+    {
+        ++nVisibleShells;
+    }
+
+    sal_uInt16 const nPreserved(100 * nVisibleShells);
+    SwCache & rCache(*SwTextFrame::GetTextCache());
+    if (rCache.GetCurMax() < nPreserved + 250)
+    {
+        rCache.IncreaseMax(nPreserved + 250 - rCache.GetCurMax());
+    }
+    rCache.SetLRUOfst(nPreserved);
+}
+
+SwSaveSetLRUOfst::~SwSaveSetLRUOfst()
+{
+    SwTextFrame::GetTextCache()->ResetLRUOfst();
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/view/viewsh.cxx b/sw/source/core/view/viewsh.cxx
index 76435e704cd9..640db966432e 100644
--- a/sw/source/core/view/viewsh.cxx
+++ b/sw/source/core/view/viewsh.cxx
@@ -700,9 +700,8 @@ void SwViewShell::LayoutIdle()
 #endif
 
     {
-        //Prepare and recover cache, so that it will not get fouled.
-        SwSaveSetLRUOfst aSave( *SwTextFrame::GetTextCache(),
-                             SwTextFrame::GetTextCache()->GetCurMax() - 50 );
+        // Preserve top of the text frame cache.
+        SwSaveSetLRUOfst aSaveLRU;
         // #125243# there are lots of stacktraces indicating that Imp() 
returns NULL
         // this SwViewShell seems to be invalid - but it's not clear why
         // this return is only a workaround!
@@ -978,9 +977,8 @@ void SwViewShell::CalcLayout()
     SET_CURR_SHELL( this );
     SwWait aWait( *GetDoc()->GetDocShell(), true );
 
-    //prepare and recover cache, so that it will not get fouled.
-    SwSaveSetLRUOfst aSaveLRU( *SwTextFrame::GetTextCache(),
-                                  SwTextFrame::GetTextCache()->GetCurMax() - 
50 );
+    // Preserve top of the text frame cache.
+    SwSaveSetLRUOfst aSaveLRU;
 
     //switch on Progress when none is running yet.
     const bool bEndProgress = SfxProgress::GetActiveProgress( 
GetDoc()->GetDocShell() ) == nullptr;
commit fed1ef4c4c246773d6f96dcd80d80d01379457c5
Author:     Michael Stahl <michael.st...@cib.de>
AuthorDate: Mon Apr 29 17:14:42 2019 +0200
Commit:     Michael Stahl <michael.st...@cib.de>
CommitDate: Tue Apr 30 15:32:36 2019 +0200

    tdf#122607 sw: remove deleted SwTextFrame's cache entry
    
    Apparently nothing else would remove the entry, and without SwTextFrame
    it's not accessible any more.
    
    If the entry was recently used, then the SwSaveSetLRUOfst usage in
    SwViewShell::CalcLayout() will preserve it instead of giving the cache
    entry to a new frame.
    
    Change-Id: Id43fdbad2ac006853928e30a7b6768c3e3dc1667
    Reviewed-on: https://gerrit.libreoffice.org/71541
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@cib.de>
    (cherry picked from commit 31ae7509003b1e650463ee1468c0b315ba13efe6)

diff --git a/sw/source/core/bastyp/swcache.cxx 
b/sw/source/core/bastyp/swcache.cxx
index 2019d7d0b3b5..ab82fe11ba74 100644
--- a/sw/source/core/bastyp/swcache.cxx
+++ b/sw/source/core/bastyp/swcache.cxx
@@ -326,6 +326,15 @@ void SwCache::DeleteObj( SwCacheObj *pObj )
     CHECK;
 }
 
+void SwCache::Delete(void const*const pOwner, sal_uInt16 const nIndex)
+{
+    INCREMENT( m_nDelete );
+    if (SwCacheObj *const pObj = Get(pOwner, nIndex, false))
+    {
+        DeleteObj(pObj);
+    }
+}
+
 void SwCache::Delete( const void *pOwner )
 {
     INCREMENT( m_nDelete );
diff --git a/sw/source/core/inc/swcache.hxx b/sw/source/core/inc/swcache.hxx
index 30410061b49f..a481bbff28ff 100644
--- a/sw/source/core/inc/swcache.hxx
+++ b/sw/source/core/inc/swcache.hxx
@@ -102,6 +102,7 @@ public:
     void ToTop( SwCacheObj *pObj );
 
     bool Insert( SwCacheObj *pNew );
+    void Delete(const void * pOwner, sal_uInt16 nIndex);
     void Delete( const void *pOwner );
 
     void SetLRUOfst( const sal_uInt16 nOfst );  /// nOfst determines how many 
are not to be touched
diff --git a/sw/source/core/text/txtfrm.cxx b/sw/source/core/text/txtfrm.cxx
index 62b281ae6974..c759be22aa02 100644
--- a/sw/source/core/text/txtfrm.cxx
+++ b/sw/source/core/text/txtfrm.cxx
@@ -693,6 +693,10 @@ void SwTextFrame::DestroyImpl()
 
 SwTextFrame::~SwTextFrame()
 {
+    if (GetCacheIdx() != USHRT_MAX)
+    {
+        s_pTextCache->Delete(this, GetCacheIdx());
+    }
 }
 
 namespace sw {
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to