[Libreoffice-commits] core.git: Branch 'libreoffice-6-2' - sc/inc sc/source

Libreoffice Gerrit user logerrit at kemper.freedesktop.org
Tue Feb 12 15:08:41 UTC 2019


 sc/inc/document.hxx                 |   24 ++++++++++++++++++++++++
 sc/source/core/data/documen2.cxx    |    1 +
 sc/source/core/data/formulacell.cxx |   21 ++++++++++++++++++++-
 sc/source/ui/docshell/docsh4.cxx    |    2 ++
 4 files changed, 47 insertions(+), 1 deletion(-)

New commits:
commit 34088a9b994f96a69a777a1cf61ab50cf789b9e6
Author:     Dennis Francis <dennis.francis at collabora.com>
AuthorDate: Tue Feb 5 16:55:08 2019 +0530
Commit:     Dennis Francis <dennis.francis at collabora.com>
CommitDate: Tue Feb 12 16:08:07 2019 +0100

    tdf#121388 : Disable threading and dep evaluation for IF...
    
    IFS/SWITCH if the call did not originate from
    ScDocShell::DoRecalc()/ScDocShell::DoHardRecalc()
    
    Change-Id: Ifdb3a496276dc841fc42a1bad1876cfb1057baf6
    Reviewed-on: https://gerrit.libreoffice.org/67414
    Tested-by: Jenkins
    Reviewed-by: Dennis Francis <dennis.francis at collabora.com>
    Reviewed-on: https://gerrit.libreoffice.org/67728
    Tested-by: Xisco FaulĂ­ <xiscofauli at libreoffice.org>

diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx
index 31278f83798b..6a584b47d0a8 100644
--- a/sc/inc/document.hxx
+++ b/sc/inc/document.hxx
@@ -540,6 +540,8 @@ private:
 
     bool                mbTrackFormulasPending  : 1;
     bool                mbFinalTrackFormulas    : 1;
+    // This indicates if a ScDocShell::DoRecalc() or ScDocShell::DoHardRecalc() is in progress.
+    bool                mbDocShellRecalc        : 1;
 
     size_t              mnMutationGuardFlags;
 
@@ -2453,6 +2455,9 @@ public:
 
     SC_DLLPUBLIC ScColumnsRange GetColumnsRange(SCTAB nTab, SCCOL nColBegin, SCCOL nColEnd) const;
 
+    bool IsInDocShellRecalc() const   { return mbDocShellRecalc; }
+    void SetDocShellRecalc(bool bSet) { mbDocShellRecalc = bSet; }
+
 private:
 
     /**
@@ -2575,6 +2580,25 @@ struct ScMutationGuard
     size_t mnFlags;
     ScDocument* mpDocument;
 #endif
+
+};
+
+class ScDocShellRecalcGuard
+{
+    ScDocument& mrDoc;
+
+public:
+    ScDocShellRecalcGuard(ScDocument& rDoc)
+        : mrDoc(rDoc)
+    {
+        assert(!mrDoc.IsInDocShellRecalc());
+        mrDoc.SetDocShellRecalc(true);
+    }
+
+    ~ScDocShellRecalcGuard()
+    {
+        mrDoc.SetDocShellRecalc(false);
+    }
 };
 
 #endif
diff --git a/sc/source/core/data/documen2.cxx b/sc/source/core/data/documen2.cxx
index 8ca890344a74..6b6a36f23149 100644
--- a/sc/source/core/data/documen2.cxx
+++ b/sc/source/core/data/documen2.cxx
@@ -159,6 +159,7 @@ ScDocument::ScDocument( ScDocumentMode eMode, SfxObjectShell* pDocShell ) :
         mbEmbedFontScriptComplex(true),
         mbTrackFormulasPending(false),
         mbFinalTrackFormulas(false),
+        mbDocShellRecalc(false),
         mnMutationGuardFlags(0)
 {
     SetStorageGrammar( formula::FormulaGrammar::GRAM_STORAGE_DEFAULT);
diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx
index edbf1ab6e92e..08cd5c1fa057 100644
--- a/sc/source/core/data/formulacell.cxx
+++ b/sc/source/core/data/formulacell.cxx
@@ -4372,8 +4372,27 @@ struct ScDependantsCalculator
 
         ScRangeList aRangeList;
         bool bHasSelfReferences = false;
-        for (auto p: mrCode.RPNTokens())
+
+        bool bInDocShellRecalc = mrDoc.IsInDocShellRecalc();
+
+        FormulaToken** pRPNArray = mrCode.GetCode();
+        sal_uInt16 nCodeLen = mrCode.GetCodeLen();
+        for (sal_Int32 nTokenIdx = nCodeLen-1; nTokenIdx >= 0; --nTokenIdx)
         {
+            auto p = pRPNArray[nTokenIdx];
+            if (!bInDocShellRecalc)
+            {
+                // The dependency evaluator evaluates all arguments of IF/IFS/SWITCH irrespective
+                // of the result of the condition expression.
+                // This is a perf problem if we *don't* intent on recalc'ing all dirty cells
+                // in the document. So lets disable threading and stop dependency evaluation if
+                // the call did not originate from ScDocShell::DoRecalc()/ScDocShell::DoHardRecalc()
+                // for formulae with IF/IFS/SWITCH
+                OpCode nOpCode = p->GetOpCode();
+                if (nOpCode == ocIf || nOpCode == ocIfs_MS || nOpCode == ocSwitch_MS)
+                    return false;
+            }
+
             switch (p->GetType())
             {
             case svSingleRef:
diff --git a/sc/source/ui/docshell/docsh4.cxx b/sc/source/ui/docshell/docsh4.cxx
index ad89b34082a6..a4312467b4fe 100644
--- a/sc/source/ui/docshell/docsh4.cxx
+++ b/sc/source/ui/docshell/docsh4.cxx
@@ -1329,6 +1329,7 @@ bool ScDocShell::ExecuteChangeProtectionDialog( bool bJustQueryIfProtected )
 
 void ScDocShell::DoRecalc( bool bApi )
 {
+    ScDocShellRecalcGuard aGuard(m_aDocument);
     bool bDone = false;
     ScTabViewShell* pSh = GetBestViewShell();
     ScInputHandler* pHdl = ( pSh ? SC_MOD()->GetInputHdl( pSh ) : nullptr );
@@ -1375,6 +1376,7 @@ void ScDocShell::DoRecalc( bool bApi )
 void ScDocShell::DoHardRecalc()
 {
     auto start = std::chrono::steady_clock::now();
+    ScDocShellRecalcGuard aGuard(m_aDocument);
     WaitObject aWaitObj( GetActiveDialogParent() );
     ScTabViewShell* pSh = GetBestViewShell();
     if ( pSh )


More information about the Libreoffice-commits mailing list