diff options
author | Dennis Francis <dennis.francis@collabora.com> | 2019-02-05 16:55:08 +0530 |
---|---|---|
committer | Dennis Francis <dennis.francis@collabora.com> | 2019-02-12 16:08:07 +0100 |
commit | 34088a9b994f96a69a777a1cf61ab50cf789b9e6 (patch) | |
tree | 19ce418a321433668473b786e1f8903e76e88d7d | |
parent | 6b5807851357059cdfc54a6870498baea6d92ee0 (diff) |
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@collabora.com>
Reviewed-on: https://gerrit.libreoffice.org/67728
Tested-by: Xisco Faulí <xiscofauli@libreoffice.org>
-rw-r--r-- | sc/inc/document.hxx | 24 | ||||
-rw-r--r-- | sc/source/core/data/documen2.cxx | 1 | ||||
-rw-r--r-- | sc/source/core/data/formulacell.cxx | 21 | ||||
-rw-r--r-- | sc/source/ui/docshell/docsh4.cxx | 2 |
4 files changed, 47 insertions, 1 deletions
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 ) |