diff --git a/sc/inc/column.hxx b/sc/inc/column.hxx index 44bee716bf18..acd899e7658a 100644 --- a/sc/inc/column.hxx +++ b/sc/inc/column.hxx @@ -583,7 +583,7 @@ public: void SetFormulaResults( SCROW nRow, const double* pResults, size_t nLen ); void SetFormulaResults( SCROW nRow, const formula::FormulaConstTokenRef* pResults, size_t nLen ); - void CalculateInThread( const ScInterpreterContext& rContext, SCROW nRow, size_t nLen, unsigned nThisThread, unsigned nThreadsTotal ); + void CalculateInThread( ScInterpreterContext& rContext, SCROW nRow, size_t nLen, unsigned nThisThread, unsigned nThreadsTotal ); void HandleStuffAfterParallelCalculation( SCROW nRow, size_t nLen ); void SetNumberFormat( SCROW nRow, sal_uInt32 nNumberFormat ); diff --git a/sc/inc/document.hxx b/sc/inc/document.hxx index 8b138378dda3..c4db749eab6a 100644 --- a/sc/inc/document.hxx +++ b/sc/inc/document.hxx @@ -458,6 +458,8 @@ private: // plain thread_local static member. thread_local static ScDocumentThreadSpecific maThreadSpecific; + mutable ScInterpreterContext maInterpreterContext; + sal_uInt16 nSrcVer; // file version (load/save) sal_uInt16 nFormulaTrackCount; HardRecalcState eHardRecalcState; // off, temporary, eternal @@ -560,10 +562,11 @@ public: SC_DLLPUBLIC void InitDrawLayer( SfxObjectShell* pDocShell = nullptr ); - ScInterpreterContext GetNonThreadedContext() const + ScInterpreterContext& GetNonThreadedContext() const { // GetFormatTable() asserts that we are not in a threaded calculation - return ScInterpreterContext(*this, GetFormatTable()); + maInterpreterContext.mpFormatter = GetFormatTable(); + return maInterpreterContext; } SC_DLLPUBLIC sfx2::LinkManager* GetLinkManager(); @@ -2056,7 +2059,7 @@ public: void SC_DLLPUBLIC SetFormulaResults( const ScAddress& rTopPos, const double* pResults, size_t nLen ); void SC_DLLPUBLIC SetFormulaResults( const ScAddress& rTopPos, const formula::FormulaConstTokenRef* pResults, size_t nLen ); - ScDocumentThreadSpecific CalculateInColumnInThread( const ScInterpreterContext& rContext, const ScAddress& rTopPos, size_t nLen, unsigned nThisThread, unsigned nThreadsTotal); + ScDocumentThreadSpecific CalculateInColumnInThread( ScInterpreterContext& rContext, const ScAddress& rTopPos, size_t nLen, unsigned nThisThread, unsigned nThreadsTotal); void HandleStuffAfterParallelCalculation( const ScAddress& rTopPos, size_t nLen ); /** diff --git a/sc/inc/formulacell.hxx b/sc/inc/formulacell.hxx index 0185e2629010..e75416de8e56 100644 --- a/sc/inc/formulacell.hxx +++ b/sc/inc/formulacell.hxx @@ -150,7 +150,7 @@ public: SCITP_FROM_ITERATION, SCITP_CLOSE_ITERATION_CIRCLE }; - void InterpretTail( const ScInterpreterContext&, ScInterpretTailParameter ); + void InterpretTail( ScInterpreterContext&, ScInterpretTailParameter ); void HandleStuffAfterParallelCalculation(); diff --git a/sc/inc/interpretercontext.hxx b/sc/inc/interpretercontext.hxx index cbf05349ca5f..ff52267dfb26 100644 --- a/sc/inc/interpretercontext.hxx +++ b/sc/inc/interpretercontext.hxx @@ -10,6 +10,11 @@ #ifndef INCLUDED_SC_INC_INTERPRETERCONTEXT_HXX #define INCLUDED_SC_INC_INTERPRETERCONTEXT_HXX +#include +#include + +#define TOKEN_CACHE_SIZE 8 + class ScDocument; class SvNumberFormatter; @@ -17,15 +22,22 @@ struct ScInterpreterContext { const ScDocument& mrDoc; SvNumberFormatter* mpFormatter; + size_t mnTokenCachePos; + std::vector maTokens; ScInterpreterContext(const ScDocument& rDoc, SvNumberFormatter* pFormatter) : mrDoc(rDoc), - mpFormatter(pFormatter) + mpFormatter(pFormatter), + mnTokenCachePos(0), + maTokens(TOKEN_CACHE_SIZE, nullptr) { } ~ScInterpreterContext() { + for ( auto p : maTokens ) + if ( p ) + p->DecRef(); } SvNumberFormatter* GetFormatTable() const diff --git a/sc/inc/table.hxx b/sc/inc/table.hxx index 1f77ae4d2e39..3721e2226a5a 100644 --- a/sc/inc/table.hxx +++ b/sc/inc/table.hxx @@ -998,7 +998,7 @@ public: void SetFormulaResults( SCCOL nCol, SCROW nRow, const double* pResults, size_t nLen ); void SetFormulaResults( SCCOL nCol, SCROW nRow, const formula::FormulaConstTokenRef* pResults, size_t nLen ); - void CalculateInColumnInThread( const ScInterpreterContext& rContext, SCCOL nCol, SCROW nRow, size_t nLen, unsigned nThisThread, unsigned nThreadsTotal); + void CalculateInColumnInThread( ScInterpreterContext& rContext, SCCOL nCol, SCROW nRow, size_t nLen, unsigned nThisThread, unsigned nThreadsTotal); void HandleStuffAfterParallelCalculation( SCCOL nCol, SCROW nRow, size_t nLen); /** diff --git a/sc/source/core/data/column2.cxx b/sc/source/core/data/column2.cxx index daeda62bd881..fea8d080dd13 100644 --- a/sc/source/core/data/column2.cxx +++ b/sc/source/core/data/column2.cxx @@ -2877,7 +2877,7 @@ void ScColumn::SetFormulaResults( SCROW nRow, const formula::FormulaConstTokenRe } } -void ScColumn::CalculateInThread( const ScInterpreterContext& rContext, SCROW nRow, size_t nLen, unsigned nThisThread, unsigned nThreadsTotal) +void ScColumn::CalculateInThread( ScInterpreterContext& rContext, SCROW nRow, size_t nLen, unsigned nThisThread, unsigned nThreadsTotal) { assert(pDocument->mbThreadedGroupCalcInProgress); diff --git a/sc/source/core/data/documen2.cxx b/sc/source/core/data/documen2.cxx index b15ee591a7e2..9bf0fcf73194 100644 --- a/sc/source/core/data/documen2.cxx +++ b/sc/source/core/data/documen2.cxx @@ -177,6 +177,7 @@ ScDocument::ScDocument( ScDocumentMode eMode, SfxObjectShell* pDocShell ) : nInterpretLevel(0), nMacroInterpretLevel(0), nInterpreterTableOpLevel(0), + maInterpreterContext( *this, nullptr ), nSrcVer( SC_CURRENT_VERSION ), nFormulaTrackCount(0), eHardRecalcState(HardRecalcState::OFF), diff --git a/sc/source/core/data/documen8.cxx b/sc/source/core/data/documen8.cxx index 8bf1de3fb191..c7be637fb073 100644 --- a/sc/source/core/data/documen8.cxx +++ b/sc/source/core/data/documen8.cxx @@ -427,7 +427,7 @@ void ScDocument::SetFormulaResults( pTab->SetFormulaResults(rTopPos.Col(), rTopPos.Row(), pResults, nLen); } -ScDocumentThreadSpecific ScDocument::CalculateInColumnInThread( const ScInterpreterContext& rContext, const ScAddress& rTopPos, size_t nLen, unsigned nThisThread, unsigned nThreadsTotal) +ScDocumentThreadSpecific ScDocument::CalculateInColumnInThread( ScInterpreterContext& rContext, const ScAddress& rTopPos, size_t nLen, unsigned nThisThread, unsigned nThreadsTotal) { ScTable* pTab = FetchTable(rTopPos.Tab()); if (!pTab) diff --git a/sc/source/core/data/formulacell.cxx b/sc/source/core/data/formulacell.cxx index e68325c59e0e..329f1afa5034 100644 --- a/sc/source/core/data/formulacell.cxx +++ b/sc/source/core/data/formulacell.cxx @@ -1746,7 +1746,7 @@ class StackCleaner }; } -void ScFormulaCell::InterpretTail( const ScInterpreterContext& rContext, ScInterpretTailParameter eTailParam ) +void ScFormulaCell::InterpretTail( ScInterpreterContext& rContext, ScInterpretTailParameter eTailParam ) { RecursionCounter aRecursionCounter( pDocument->GetRecursionHelper(), this); nSeenInIteration = pDocument->GetRecursionHelper().GetIteration(); diff --git a/sc/source/core/data/table1.cxx b/sc/source/core/data/table1.cxx index e43ab0efc7ac..0b23c7474e91 100644 --- a/sc/source/core/data/table1.cxx +++ b/sc/source/core/data/table1.cxx @@ -2338,7 +2338,7 @@ void ScTable::SetFormulaResults( aCol[nCol].SetFormulaResults(nRow, pResults, nLen); } -void ScTable::CalculateInColumnInThread( const ScInterpreterContext& rContext, SCCOL nCol, SCROW nRow, size_t nLen, unsigned nThisThread, unsigned nThreadsTotal) +void ScTable::CalculateInColumnInThread( ScInterpreterContext& rContext, SCCOL nCol, SCROW nRow, size_t nLen, unsigned nThisThread, unsigned nThreadsTotal) { if (!ValidCol(nCol)) return; diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx index a6eaf5cd78ae..d6a77f2b9c1a 100644 --- a/sc/source/core/inc/interpre.hxx +++ b/sc/source/core/inc/interpre.hxx @@ -97,7 +97,6 @@ class SharedStringPool; } #define MAXSTACK (4096 / sizeof(formula::FormulaToken*)) -#define TOKEN_CACHE_SIZE 8 class ScTokenStack { @@ -200,7 +199,7 @@ private: formula::FormulaTokenIterator aCode; ScAddress aPos; ScTokenArray& rArr; - const ScInterpreterContext& mrContext; + ScInterpreterContext& mrContext; ScDocument* pDok; sfx2::LinkManager* mpLinkManager; svl::SharedStringPool& mrStrPool; @@ -230,8 +229,6 @@ private: bool bMatrixFormula; // formula cell is a matrix formula VolatileType meVolatileType; - size_t mnTokenCachePos; - std::vector maTokenCache; /// Merge global and document specific settings. void MergeCalcConfig(); @@ -994,7 +991,7 @@ private: double GetTInv( double fAlpha, double fSize, int nType ); public: - ScInterpreter( ScFormulaCell* pCell, ScDocument* pDoc, const ScInterpreterContext& rContext, + ScInterpreter( ScFormulaCell* pCell, ScDocument* pDoc, ScInterpreterContext& rContext, const ScAddress&, ScTokenArray& ); ~ScInterpreter(); diff --git a/sc/source/core/tool/formulagroup.cxx b/sc/source/core/tool/formulagroup.cxx index a29030557032..f6565e732086 100644 --- a/sc/source/core/tool/formulagroup.cxx +++ b/sc/source/core/tool/formulagroup.cxx @@ -155,6 +155,7 @@ public: ScAddress aBatchTopPos, const ScAddress& rTopPos, ScDocument& rDoc, + SvNumberFormatter* pFormatter, std::vector& rRes, SCROW nIndex, SCROW nLastIndex) : @@ -162,6 +163,7 @@ public: maBatchTopPos(aBatchTopPos), mrTopPos(rTopPos), mrDoc(rDoc), + mpFormatter(pFormatter), mrResults(rRes), mnIdx(nIndex), mnLastIdx(nLastIndex) @@ -296,7 +298,8 @@ public: ScCompiler aComp(&mrDoc, maBatchTopPos, aCode2); aComp.CompileTokenArray(); - ScInterpreter aInterpreter(pDest, &mrDoc, mrDoc.GetNonThreadedContext(), maBatchTopPos, aCode2); + ScInterpreterContext aContext(mrDoc, mpFormatter); + ScInterpreter aInterpreter(pDest, &mrDoc, aContext, maBatchTopPos, aCode2); aInterpreter.Interpret(); mrResults[i] = aInterpreter.GetResultToken(); } // Row iteration for loop end @@ -307,6 +310,7 @@ private: ScAddress maBatchTopPos; const ScAddress& mrTopPos; ScDocument& mrDoc; + SvNumberFormatter* mpFormatter; std::vector& mrResults; SCROW mnIdx; SCROW mnLastIdx; @@ -333,11 +337,12 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres ScAddress aBatchTopPos, const ScAddress& rTopPos2, ScDocument& rDoc2, + SvNumberFormatter* pFormatter2, std::vector& rRes, SCROW nIndex, SCROW nLastIndex) : comphelper::ThreadTask(rTag), - maSWIFunc(rCode2, aBatchTopPos, rTopPos2, rDoc2, rRes, nIndex, nLastIndex) + maSWIFunc(rCode2, aBatchTopPos, rTopPos2, rDoc2, pFormatter2, rRes, nIndex, nLastIndex) { } virtual void doWork() override @@ -353,6 +358,8 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres bool bUseThreading = !bThreadingProhibited && officecfg::Office::Calc::Formula::Calculation::UseThreadedCalculationForFormulaGroups::get(); + SvNumberFormatter* pFormatter = rDoc.GetNonThreadedContext().GetFormatTable(); + if (bUseThreading) { comphelper::ThreadPool& rThreadPool(comphelper::ThreadPool::getSharedOptimalPool()); @@ -381,7 +388,7 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres if ( nRemaining ) --nRemaining; SCROW nLast = nStart + nCount - 1; - rThreadPool.pushTask(new Executor(aTag, rCode, aTmpPos, rTopPos, rDoc, aResults, nStart, nLast)); + rThreadPool.pushTask(new Executor(aTag, rCode, aTmpPos, rTopPos, rDoc, pFormatter, aResults, nStart, nLast)); aTmpPos.IncRow(nCount); nLeft -= nCount; nStart = nLast + 1; @@ -392,7 +399,7 @@ bool FormulaGroupInterpreterSoftware::interpret(ScDocument& rDoc, const ScAddres } else { - SoftwareInterpreterFunc aSWIFunc(rCode, aTmpPos, rTopPos, rDoc, aResults, 0, xGroup->mnLength - 1); + SoftwareInterpreterFunc aSWIFunc(rCode, aTmpPos, rTopPos, rDoc, pFormatter, aResults, 0, xGroup->mnLength - 1); aSWIFunc(); } diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx index 9ce2d00dde17..28f14137f077 100644 --- a/sc/source/core/tool/interpr4.cxx +++ b/sc/source/core/tool/interpr4.cxx @@ -1730,15 +1730,13 @@ void ScInterpreter::QueryMatrixType(const ScMatrixRef& xMat, short& rRetTypeExpr formula::FormulaToken* ScInterpreter::CreateFormulaDoubleToken( double fVal, short nFmt ) { - if ( maTokenCache.size() != TOKEN_CACHE_SIZE ) - maTokenCache.resize( TOKEN_CACHE_SIZE ); + assert( mrContext.maTokens.size() == TOKEN_CACHE_SIZE ); // Find a spare token - for ( auto p : maTokenCache ) + for ( auto p : mrContext.maTokens ) { if (p && p->GetRef() == 1) { - p->IncRef(); p->GetDoubleAsReference() = fVal; p->SetDoubleType( nFmt ); return p; @@ -1747,12 +1745,11 @@ formula::FormulaToken* ScInterpreter::CreateFormulaDoubleToken( double fVal, sho // Allocate a new token auto p = new FormulaTypedDoubleToken( fVal, nFmt ); - size_t pos = (mnTokenCachePos++) % TOKEN_CACHE_SIZE; - if ( maTokenCache[pos] ) - maTokenCache[pos]->DecRef(); - maTokenCache[pos] = p; + if ( mrContext.maTokens[mrContext.mnTokenCachePos] ) + mrContext.maTokens[mrContext.mnTokenCachePos]->DecRef(); + mrContext.maTokens[mrContext.mnTokenCachePos] = p; p->IncRef(); - + mrContext.mnTokenCachePos = (mrContext.mnTokenCachePos + 1) % TOKEN_CACHE_SIZE; return p; } @@ -3811,7 +3808,7 @@ void ScInterpreter::ScTTT() PushError(FormulaError::NoValue); } -ScInterpreter::ScInterpreter( ScFormulaCell* pCell, ScDocument* pDoc, const ScInterpreterContext& rContext, +ScInterpreter::ScInterpreter( ScFormulaCell* pCell, ScDocument* pDoc, ScInterpreterContext& rContext, const ScAddress& rPos, ScTokenArray& r ) : aCode(r) , aPos(rPos) @@ -3871,11 +3868,6 @@ ScInterpreter::~ScInterpreter() else delete pStackObj; delete pTokenMatrixMap; - - for ( auto p : maTokenCache ) - if ( p && p->GetRef() == 1 ) - p->DecRef(); - } ScCalcConfig& ScInterpreter::GetOrCreateGlobalConfig()