summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--formula/source/core/api/token.cxx10
-rw-r--r--include/formula/token.hxx2
-rw-r--r--sc/source/core/inc/interpre.hxx4
-rw-r--r--sc/source/core/tool/interpr4.cxx45
4 files changed, 55 insertions, 6 deletions
diff --git a/formula/source/core/api/token.cxx b/formula/source/core/api/token.cxx
index 04c4a203284d..2ed68521e720 100644
--- a/formula/source/core/api/token.cxx
+++ b/formula/source/core/api/token.cxx
@@ -216,6 +216,11 @@ short FormulaToken::GetDoubleType() const
return 0;
}
+void FormulaToken::SetDoubleType( short )
+{
+ SAL_WARN( "formula.core", "FormulaToken::SetDoubleType: virtual dummy called" );
+}
+
svl::SharedString FormulaToken::GetString() const
{
SAL_WARN( "formula.core", "FormulaToken::GetString: virtual dummy called" );
@@ -1797,6 +1802,11 @@ short FormulaTypedDoubleToken::GetDoubleType() const
return mnType;
}
+void FormulaTypedDoubleToken::SetDoubleType( short nType )
+{
+ mnType = nType;
+}
+
bool FormulaTypedDoubleToken::operator==( const FormulaToken& r ) const
{
return FormulaDoubleToken::operator==( r ) && mnType == r.GetDoubleType();
diff --git a/include/formula/token.hxx b/include/formula/token.hxx
index 9b06ae48182c..3de7c761d658 100644
--- a/include/formula/token.hxx
+++ b/include/formula/token.hxx
@@ -181,6 +181,7 @@ public:
virtual double GetDouble() const;
virtual double& GetDoubleAsReference();
virtual short GetDoubleType() const;
+ virtual void SetDoubleType( short nType );
virtual svl::SharedString GetString() const;
virtual void SetString( const svl::SharedString& rStr );
virtual sal_uInt16 GetIndex() const;
@@ -321,6 +322,7 @@ public:
virtual FormulaToken* Clone() const override { return new FormulaTypedDoubleToken(*this); }
virtual short GetDoubleType() const override;
+ virtual void SetDoubleType( short nType ) override;
virtual bool operator==( const FormulaToken& rToken ) const override;
DECL_FIXEDMEMPOOL_NEWDEL_DLL( FormulaTypedDoubleToken )
diff --git a/sc/source/core/inc/interpre.hxx b/sc/source/core/inc/interpre.hxx
index 8a240e617261..a6eaf5cd78ae 100644
--- a/sc/source/core/inc/interpre.hxx
+++ b/sc/source/core/inc/interpre.hxx
@@ -97,6 +97,7 @@ class SharedStringPool;
}
#define MAXSTACK (4096 / sizeof(formula::FormulaToken*))
+#define TOKEN_CACHE_SIZE 8
class ScTokenStack
{
@@ -229,6 +230,8 @@ private:
bool bMatrixFormula; // formula cell is a matrix formula
VolatileType meVolatileType;
+ size_t mnTokenCachePos;
+ std::vector<formula::FormulaToken*> maTokenCache;
/// Merge global and document specific settings.
void MergeCalcConfig();
@@ -395,6 +398,7 @@ private:
sc::RangeMatrix PopRangeMatrix();
void QueryMatrixType(const ScMatrixRef& xMat, short& rRetTypeExpr, sal_uLong& rRetIndexExpr);
+ formula::FormulaToken* CreateFormulaDoubleToken( double fVal, short nFmt = css::util::NumberFormat::NUMBER );
formula::FormulaToken* CreateDoubleOrTypedToken( double fVal );
void PushDouble(double nVal);
diff --git a/sc/source/core/tool/interpr4.cxx b/sc/source/core/tool/interpr4.cxx
index 73e91cfb6271..9ce2d00dde17 100644
--- a/sc/source/core/tool/interpr4.cxx
+++ b/sc/source/core/tool/interpr4.cxx
@@ -731,7 +731,7 @@ void ScInterpreter::PushCellResultToken( bool bDisplayEmptyAsString,
{
TreatDoubleError( fVal);
if (!IfErrorPushError())
- PushTempTokenWithoutError( new FormulaDoubleToken( fVal));
+ PushTempTokenWithoutError( CreateFormulaDoubleToken( fVal));
}
else
{
@@ -1687,7 +1687,7 @@ void ScInterpreter::QueryMatrixType(const ScMatrixRef& xMat, short& rRetTypeExpr
{
if ( xMat->IsEmptyPath( 0, 0))
{ // result of empty FALSE jump path
- FormulaTokenRef xRes = new FormulaDoubleToken( 0.0);
+ FormulaTokenRef xRes = CreateFormulaDoubleToken( 0.0);
PushTempToken( new ScMatrixFormulaCellToken(nCols, nRows, xMat, xRes.get()));
rRetTypeExpr = css::util::NumberFormat::LOGICAL;
}
@@ -1716,7 +1716,7 @@ void ScInterpreter::QueryMatrixType(const ScMatrixRef& xMat, short& rRetTypeExpr
if (nErr != FormulaError::NONE)
xRes = new FormulaErrorToken( nErr);
else
- xRes = new FormulaDoubleToken( nMatVal.fVal);
+ xRes = CreateFormulaDoubleToken( nMatVal.fVal);
PushTempToken( new ScMatrixFormulaCellToken(nCols, nRows, xMat, xRes.get()));
if ( rRetTypeExpr != css::util::NumberFormat::LOGICAL )
rRetTypeExpr = css::util::NumberFormat::NUMBER;
@@ -1728,14 +1728,42 @@ void ScInterpreter::QueryMatrixType(const ScMatrixRef& xMat, short& rRetTypeExpr
SetError( FormulaError::UnknownStackVariable);
}
+formula::FormulaToken* ScInterpreter::CreateFormulaDoubleToken( double fVal, short nFmt )
+{
+ if ( maTokenCache.size() != TOKEN_CACHE_SIZE )
+ maTokenCache.resize( TOKEN_CACHE_SIZE );
+
+ // Find a spare token
+ for ( auto p : maTokenCache )
+ {
+ if (p && p->GetRef() == 1)
+ {
+ p->IncRef();
+ p->GetDoubleAsReference() = fVal;
+ p->SetDoubleType( nFmt );
+ return p;
+ }
+ }
+
+ // 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;
+ p->IncRef();
+
+ return p;
+}
+
formula::FormulaToken* ScInterpreter::CreateDoubleOrTypedToken( double fVal )
{
// NumberFormat::NUMBER is the default untyped double.
if (nFuncFmtType && nFuncFmtType != css::util::NumberFormat::NUMBER &&
nFuncFmtType != css::util::NumberFormat::UNDEFINED)
- return new FormulaTypedDoubleToken( fVal, nFuncFmtType);
+ return CreateFormulaDoubleToken( fVal, nFuncFmtType);
else
- return new FormulaDoubleToken( fVal);
+ return CreateFormulaDoubleToken( fVal);
}
void ScInterpreter::PushDouble(double nVal)
@@ -3843,6 +3871,11 @@ ScInterpreter::~ScInterpreter()
else
delete pStackObj;
delete pTokenMatrixMap;
+
+ for ( auto p : maTokenCache )
+ if ( p && p->GetRef() == 1 )
+ p->DecRef();
+
}
ScCalcConfig& ScInterpreter::GetOrCreateGlobalConfig()
@@ -4584,7 +4617,7 @@ StackVar ScInterpreter::Interpret()
nRetIndexExpr = 0; // carry format index only for matching type
nRetTypeExpr = nFuncFmtType = nCurFmtType;
}
- PushTempToken( new FormulaDoubleToken( fVal));
+ PushTempToken( CreateFormulaDoubleToken( fVal));
}
if ( nFuncFmtType == css::util::NumberFormat::UNDEFINED )
{