diff options
-rw-r--r-- | formula/inc/formula/compiler.hrc | 4 | ||||
-rw-r--r-- | formula/inc/formula/tokenarray.hxx | 6 | ||||
-rw-r--r-- | formula/source/core/api/token.cxx | 6 | ||||
-rw-r--r-- | sc/inc/tokenarray.hxx | 10 | ||||
-rw-r--r-- | sc/source/core/tool/token.cxx | 80 |
5 files changed, 104 insertions, 2 deletions
diff --git a/formula/inc/formula/compiler.hrc b/formula/inc/formula/compiler.hrc index 8acfff652d07..053947c2a796 100644 --- a/formula/inc/formula/compiler.hrc +++ b/formula/inc/formula/compiler.hrc @@ -94,6 +94,8 @@ #define SC_OPCODE_NEG_SUB 62 #define SC_OPCODE_STOP_UN_OP 63 +#define SC_OPCODE_START_FUNCTION 65 + /*** Functions without parameters ***/ #define SC_OPCODE_START_NO_PAR 65 #define SC_OPCODE_PI 65 @@ -403,6 +405,8 @@ #define SC_OPCODE_STOP_2_PAR 407 #define SC_OPCODE_LAST_OPCODE_ID 406 /* last OpCode */ +#define SC_OPCODE_STOP_FUNCTION 407 + /*** Internal ***/ #define SC_OPCODE_INTERNAL_BEGIN 9999 #define SC_OPCODE_TTT 9999 diff --git a/formula/inc/formula/tokenarray.hxx b/formula/inc/formula/tokenarray.hxx index 42c92127c856..875b055a621a 100644 --- a/formula/inc/formula/tokenarray.hxx +++ b/formula/inc/formula/tokenarray.hxx @@ -192,6 +192,12 @@ public: */ bool Fill(const com::sun::star::uno::Sequence< com::sun::star::sheet::FormulaToken >& _aSequence, ExternalReferenceHelper* _pRef = NULL); + /** + * Do some checking based on the individual tokens. For now, we use this + * only to check whether we can vectorize the token array. + */ + virtual void CheckToken( const FormulaToken& t ); + FormulaToken* AddToken( const FormulaToken& ); FormulaToken* AddString( const sal_Unicode* pStr ); FormulaToken* AddString( const String& rStr ); diff --git a/formula/source/core/api/token.cxx b/formula/source/core/api/token.cxx index 875055519ddd..84180f02fcf1 100644 --- a/formula/source/core/api/token.cxx +++ b/formula/source/core/api/token.cxx @@ -708,6 +708,11 @@ void FormulaTokenArray::Clear() ClearRecalcMode(); } +void FormulaTokenArray::CheckToken( const FormulaToken& /*r*/ ) +{ + // Do nothing. +} + FormulaToken* FormulaTokenArray::AddToken( const FormulaToken& r ) { return Add( r.Clone() ); @@ -724,6 +729,7 @@ FormulaToken* FormulaTokenArray::Add( FormulaToken* t ) pCode = new FormulaToken*[ MAXCODE ]; if( nLen < MAXCODE-1 ) { + CheckToken(*t); pCode[ nLen++ ] = t; if( t->GetOpCode() == ocPush && ( t->GetType() == svSingleRef || t->GetType() == svDoubleRef ) ) diff --git a/sc/inc/tokenarray.hxx b/sc/inc/tokenarray.hxx index e3b7d5679272..5c09d288b7af 100644 --- a/sc/inc/tokenarray.hxx +++ b/sc/inc/tokenarray.hxx @@ -33,9 +33,18 @@ struct ScComplexRefData; class SC_DLLPUBLIC ScTokenArray : public formula::FormulaTokenArray { friend class ScCompiler; + + /** + * When vectorization is enabled, we could potentially mass-calculate a + * series of formula token arrays in adjacent formula cells in one step, + * provided that they all contain identical set of tokens. + */ + enum VectorState { Disabled = 0, Enabled, CheckReference }; + bool ImplGetReference( ScRange& rRange, bool bValidOnly ) const; size_t mnHashValue; + VectorState meVectorState; public: ScTokenArray(); @@ -61,6 +70,7 @@ public: formula::FormulaToken* AddRawToken( const ScRawToken& ); virtual bool AddFormulaToken(const com::sun::star::sheet::FormulaToken& _aToken,formula::ExternalReferenceHelper* _pRef); + virtual void CheckToken( const formula::FormulaToken& r ); virtual formula::FormulaToken* AddOpCode( OpCode eCode ); /** ScSingleRefToken with ocPush. */ formula::FormulaToken* AddSingleReference( const ScSingleRefData& rRef ); diff --git a/sc/source/core/tool/token.cxx b/sc/source/core/tool/token.cxx index b59517756202..a5eb79679b31 100644 --- a/sc/source/core/tool/token.cxx +++ b/sc/source/core/tool/token.cxx @@ -1246,6 +1246,78 @@ bool ScTokenArray::AddFormulaToken(const com::sun::star::sheet::FormulaToken& _a } return bError; } + +void ScTokenArray::CheckToken( const FormulaToken& r ) +{ + if (meVectorState == Disabled) + // It's already disabled. No more checking needed. + return; + + OpCode eOp = r.GetOpCode(); + + if (SC_OPCODE_START_FUNCTION <= eOp && eOp < SC_OPCODE_STOP_FUNCTION) + { + // This is a function opcode. For now, we only support vectorization + // for min, max, sum and average. + switch (eOp) + { + case ocAverage: + case ocMin: + case ocMinA: + case ocMax: + case ocMaxA: + case ocSum: + // Don't change the state. + break; + default: + meVectorState = Disabled; + } + return; + } + + if (eOp == ocPush) + { + // This is a stack variable. See if this is a reference. + + switch (r.GetType()) + { + case svByte: + case svDouble: + case svString: + // Don't change the state. + break; + case svSingleRef: + case svDoubleRef: + // Depends on the reference state. + meVectorState = CheckReference; + break; + case svError: + case svEmptyCell: + case svExternal: + case svExternalDoubleRef: + case svExternalName: + case svExternalSingleRef: + case svFAP: + case svHybridCell: + case svHybridValueCell: + case svIndex: + case svJump: + case svJumpMatrix: + case svMatrix: + case svMatrixCell: + case svMissing: + case svRefList: + case svSep: + case svSubroutine: + case svUnknown: + // We don't support vectorization on these. + meVectorState = Disabled; + default: + ; + } + } +} + bool ScTokenArray::ImplGetReference( ScRange& rRange, bool bValidOnly ) const { bool bIs = false; @@ -1380,13 +1452,15 @@ bool ScTokenArray::IsValidReference( ScRange& rRange ) const ScTokenArray::ScTokenArray() : FormulaTokenArray(), - mnHashValue(0) + mnHashValue(0), + meVectorState(Enabled) { } ScTokenArray::ScTokenArray( const ScTokenArray& rArr ) : FormulaTokenArray(rArr), - mnHashValue(rArr.mnHashValue) + mnHashValue(rArr.mnHashValue), + meVectorState(rArr.meVectorState) { } @@ -1411,6 +1485,8 @@ ScTokenArray* ScTokenArray::Clone() const p->nError = nError; p->bHyperLink = bHyperLink; p->mnHashValue = mnHashValue; + p->meVectorState = meVectorState; + FormulaToken** pp; if( nLen ) { |