Browse Source

Move usedTables to a separate base class

Although this is complicating the inheritance structure, it allows constants
annotations and selects to lose 16bytes (12 in 32bit).

It is possible caching isSelectRootAndActive in a flag variable would
slighlty speed up the derived code in the select base.

Signed-off-by: Gavin Halliday <gavin.halliday@lexisnexis.com>
Gavin Halliday 13 years ago
parent
commit
29014145e6
2 changed files with 144 additions and 61 deletions
  1. 92 41
      ecl/hql/hqlexpr.cpp
  2. 52 20
      ecl/hql/hqlexpr.ipp

+ 92 - 41
ecl/hql/hqlexpr.cpp

@@ -4376,6 +4376,21 @@ IHqlExpression * CHqlExpression::commonUpExpression()
     return match;
 }
 
+IHqlExpression * CHqlExpression::calcNormalizedSelector() const
+{
+    IHqlExpression * left = &operands.item(0);
+    IHqlExpression * normalizedLeft = left->queryNormalizedSelector();
+    if ((normalizedLeft != left) || ((operands.ordinality() > 2) && hasProperty(newAtom)))
+    {
+        HqlExprArray args;
+        appendArray(args, operands);
+        args.replace(*LINK(normalizedLeft), 0);
+        removeProperty(args, newAtom);
+        return doCreateSelectExpr(args);
+    }
+    return NULL;
+}
+
 void displayHqlCacheStats()
 {
 #if 0
@@ -4403,14 +4418,8 @@ void displayHqlCacheStats()
 }
 //--------------------------------------------------------------------------------------------------------------
 
-CHqlExpressionWithType::CHqlExpressionWithType(node_operator _op, ITypeInfo * _type)
-: CHqlExpression(_op)
-{
-    type = _type;
-}
-
 CHqlExpressionWithType::CHqlExpressionWithType(node_operator _op, ITypeInfo * _type, HqlExprArray & _ownedOperands)
-: CHqlExpression(_op)
+: CHqlExpressionWithTables(_op)
 {
     type = _type;
     setOperands(_ownedOperands); // after type is initialized
@@ -4744,14 +4753,14 @@ void CUsedTablesBuilder::removeRows(IHqlExpression * expr, IHqlExpression * left
 //---------------------------------------------------------------------------------------------------------------------
 
 //Don't need to check if already visited, because the information is cached in the expression itself.
-void CHqlExpression::cacheChildrenTablesUsed(CUsedTablesBuilder & used, unsigned from, unsigned to)
+void CHqlExpressionWithTables::cacheChildrenTablesUsed(CUsedTablesBuilder & used, unsigned from, unsigned to)
 {
     for (unsigned i=from; i < to; i++)
         queryChild(i)->gatherTablesUsed(used);
 }
 
 
-void CHqlExpression::cacheInheritChildTablesUsed(IHqlExpression * ds, CUsedTablesBuilder & used, const HqlExprCopyArray & childInScopeTables)
+void CHqlExpressionWithTables::cacheInheritChildTablesUsed(IHqlExpression * ds, CUsedTablesBuilder & used, const HqlExprCopyArray & childInScopeTables)
 {
     //The argument to the operator is a new table, don't inherit grandchildren
     used.addNewTable(ds);
@@ -4767,7 +4776,7 @@ void CHqlExpression::cacheInheritChildTablesUsed(IHqlExpression * ds, CUsedTable
     }
 }
 
-void CHqlExpression::cacheTableUseage(CUsedTablesBuilder & used, IHqlExpression * expr)
+void CHqlExpressionWithTables::cacheTableUseage(CUsedTablesBuilder & used, IHqlExpression * expr)
 {
 #ifdef GATHER_HIDDEN_SELECTORS
     expr->gatherTablesUsed(used);
@@ -4785,7 +4794,7 @@ void CHqlExpression::cacheTableUseage(CUsedTablesBuilder & used, IHqlExpression
 #endif
 }
 
-void CHqlExpression::cachePotentialTablesUsed(CUsedTablesBuilder & used)
+void CHqlExpressionWithTables::cachePotentialTablesUsed(CUsedTablesBuilder & used)
 {
     ForEachChild(i, this)
     {
@@ -4798,7 +4807,7 @@ void CHqlExpression::cachePotentialTablesUsed(CUsedTablesBuilder & used)
 }
 
 
-void CHqlExpression::cacheTablesProcessChildScope(CUsedTablesBuilder & used)
+void CHqlExpressionWithTables::cacheTablesProcessChildScope(CUsedTablesBuilder & used)
 {
     unsigned max = numChildren();
     switch (getChildDatasetType(this))
@@ -4931,7 +4940,7 @@ void CHqlExpression::cacheTablesProcessChildScope(CUsedTablesBuilder & used)
 }
 
 
-void CHqlExpression::cacheTablesUsed()
+void CHqlExpressionWithTables::cacheTablesUsed()
 {
     if (!(infoFlags & HEFgatheredNew))
     {
@@ -4955,14 +4964,16 @@ void CHqlExpression::cacheTablesUsed()
         case no_select:
             {
                 IHqlExpression * ds = queryChild(0);
-                if (hasProperty(newAtom) || ((ds->getOperator() == no_select) && ds->isDatarow()))
+                if (isSelectRootAndActive())
+                {
+                    usedTables.setActiveTable(ds);
+                }
+                else
                 {
                     //MORE: ds->gatherTablesUsed(usedTables);
                     //which could ideally clone
                     specialCased = false;
                 }
-                else
-                    usedTables.setActiveTable(ds);
                 break;
             }
         case no_activerow:
@@ -5000,7 +5011,7 @@ void CHqlExpression::cacheTablesUsed()
                 case no_select:
                     {
                         IHqlExpression * ds = queryChild(0);
-                        dbgassertex(hasProperty(newAtom) || ((ds->getOperator() == no_select) && ds->isDatarow()));
+                        dbgassertex(!isSelectRootAndActive());
                         ds->gatherTablesUsed(used);
                         break;
                     }
@@ -5117,45 +5128,30 @@ void CHqlExpression::cacheTablesUsed()
     }
 }
 
-bool CHqlExpression::isIndependentOfScope()
+bool CHqlExpressionWithTables::isIndependentOfScope()
 {
     cacheTablesUsed();
     return usedTables.isIndependentOfScope();
 }
 
-bool CHqlExpression::usesSelector(IHqlExpression * selector)
+bool CHqlExpressionWithTables::usesSelector(IHqlExpression * selector)
 {
     cacheTablesUsed();
     return usedTables.usesSelector(selector);
 }
 
-void CHqlExpression::gatherTablesUsed(HqlExprCopyArray * newScope, HqlExprCopyArray * inScope)
+void CHqlExpressionWithTables::gatherTablesUsed(HqlExprCopyArray * newScope, HqlExprCopyArray * inScope)
 {
     cacheTablesUsed();
     usedTables.gatherTablesUsed(newScope, inScope);
 }
 
-void CHqlExpression::gatherTablesUsed(CUsedTablesBuilder & used)
+void CHqlExpressionWithTables::gatherTablesUsed(CUsedTablesBuilder & used)
 {
     cacheTablesUsed();
     usedTables.gatherTablesUsed(used);
 }
 
-IHqlExpression * CHqlExpression::calcNormalizedSelector() const
-{
-    IHqlExpression * left = &operands.item(0);
-    IHqlExpression * normalizedLeft = left->queryNormalizedSelector();
-    if ((normalizedLeft != left) || ((operands.ordinality() > 2) && hasProperty(newAtom)))
-    {
-        HqlExprArray args;
-        appendArray(args, operands);
-        args.replace(*LINK(normalizedLeft), 0);
-        removeProperty(args, newAtom);
-        return doCreateSelectExpr(args);
-    }
-    return NULL;
-}
-
 //==============================================================================================================
 
 CHqlSelectBaseExpression::CHqlSelectBaseExpression()
@@ -5241,6 +5237,61 @@ IHqlExpression * CHqlSelectBaseExpression::makeSelectExpression(HqlExprArray & o
     return select->closeExpr();
 }
 
+
+bool CHqlSelectBaseExpression::isIndependentOfScope()
+{
+    IHqlExpression * ds = queryChild(0);
+    if (isSelectRootAndActive())
+    {
+        return false;
+    }
+    else
+    {
+        return ds->isIndependentOfScope();
+    }
+}
+
+bool CHqlSelectBaseExpression::usesSelector(IHqlExpression * selector)
+{
+    IHqlExpression * ds = queryChild(0);
+    if (isSelectRootAndActive())
+    {
+        return (selector == ds);
+    }
+    else
+    {
+        return ds->usesSelector(selector);
+    }
+}
+
+void CHqlSelectBaseExpression::gatherTablesUsed(CUsedTablesBuilder & used)
+{
+    IHqlExpression * ds = queryChild(0);
+    if (isSelectRootAndActive())
+    {
+        used.addActiveTable(ds);
+    }
+    else
+    {
+        ds->gatherTablesUsed(used);
+    }
+}
+
+void CHqlSelectBaseExpression::gatherTablesUsed(HqlExprCopyArray * newScope, HqlExprCopyArray * inScope)
+{
+    IHqlExpression * ds = queryChild(0);
+    if (isSelectRootAndActive())
+    {
+        if (inScope)
+            ::addActiveTable(*inScope, ds);
+    }
+    else
+    {
+        ds->gatherTablesUsed(newScope, inScope);
+    }
+}
+
+
 //==============================================================================================================
 
 IHqlExpression * CHqlNormalizedSelectExpression::queryNormalizedSelector(bool skipIndex)
@@ -5905,12 +5956,12 @@ node_operator queryTableMode(IHqlExpression * expr)
 
 //==============================================================================================================
 
-CHqlRecord::CHqlRecord() : CHqlExpression (no_record)
+CHqlRecord::CHqlRecord() : CHqlExpressionWithTables(no_record)
 {
     thisAlignment = 0;
 }
 
-CHqlRecord::CHqlRecord(HqlExprArray &operands) : CHqlExpression (no_record)
+CHqlRecord::CHqlRecord(HqlExprArray &operands) : CHqlExpressionWithTables(no_record)
 {
     setOperands(operands);
     thisAlignment = 0;
@@ -6341,7 +6392,7 @@ ITypeInfo * CHqlAnnotation::getType()
 //==============================================================================================================
 
 CHqlCachedBoundFunction::CHqlCachedBoundFunction(IHqlExpression *func, bool _forceOutOfLineExpansion)
-: CHqlExpression(no_bound_func)
+: CHqlExpressionWithTables(no_bound_func)
 {
     appendOperands(LINK(func), NULL);
     if (_forceOutOfLineExpansion)
@@ -8871,7 +8922,7 @@ StringBuffer &CHqlVariable::toString(StringBuffer &ret)
 
 //==============================================================================================================
 
-CHqlAttribute::CHqlAttribute(node_operator _op, _ATOM _name) : CHqlExpression(_op)
+CHqlAttribute::CHqlAttribute(node_operator _op, _ATOM _name) : CHqlExpressionWithTables(_op)
 {
     name = _name;
 }
@@ -9209,7 +9260,7 @@ bool CHqlDelayedScopeCall::hasBaseClass(IHqlExpression * searchBase)
 #pragma warning( disable : 4355 )
 #endif
 /* In parm: scope is linked */
-CHqlAlienType::CHqlAlienType(_ATOM _name, IHqlScope *_scope, IHqlExpression * _funcdef) : CHqlExpression(no_type)
+CHqlAlienType::CHqlAlienType(_ATOM _name, IHqlScope *_scope, IHqlExpression * _funcdef) : CHqlExpressionWithTables(no_type)
 {
     name = _name;
     scope = _scope;

+ 52 - 20
ecl/hql/hqlexpr.ipp

@@ -20,7 +20,7 @@
 
 #define NUM_PARALLEL_TRANSFORMS 1
 //I'm not sure if the following is needed or not - I'm slight concerned that remote scopes (e.g.,, plugins)
-//may be accessed in parallel fro mmultiple threads, causing potential conflicts
+//may be accessed in parallel from multiple threads, causing potential conflicts
 #define THREAD_SAFE_SYMBOLS
 
 #include "jexcept.hpp"
@@ -129,7 +129,6 @@ protected:
 
     CHqlDynamicAttribute * attributes;
     HqlExprArray operands;
-    CUsedTables usedTables;
 
 protected:
     CHqlExpression(node_operator op);
@@ -145,6 +144,18 @@ protected:
     inline bool fullyBound() const { return (infoFlags & HEFunbound) == 0; }
     inline bool pure() const { return (infoFlags & HEFimpure) == 0; }
 
+    //For a no_select, is this the root no_select (rather than a.b.c), and is it also an active selector.
+    //Used for determining how a no_select should be interpreted e.g., in table gathering. 
+    inline bool isSelectRootAndActive() const
+    {
+        if (hasProperty(newAtom))
+            return false;
+        IHqlExpression * ds = queryChild(0);
+        if ((ds->getOperator() == no_select) && ds->isDatarow())
+            return false;
+        return true;
+    }
+
     bool isAggregate();
     IHqlExpression * commonUpExpression();
 
@@ -161,18 +172,10 @@ protected:
     void updateFlagsAfterOperands();
 
     IHqlExpression * calcNormalizedSelector() const;
-    void mergeGathered(CopyArray &, CopyArray &);
     IHqlExpression *fixScope(IHqlDataset *table);
     virtual unsigned getCachedEclCRC();
     void setInitialHash(unsigned typeHash);
 
-    void cacheChildrenTablesUsed(CUsedTablesBuilder & used, unsigned from, unsigned to);
-    void cacheInheritChildTablesUsed(IHqlExpression * ds, CUsedTablesBuilder & used, const HqlExprCopyArray & childInScopeTables);
-    void cachePotentialTablesUsed(CUsedTablesBuilder & used);
-    void cacheTablesProcessChildScope(CUsedTablesBuilder & used);
-    void cacheTablesUsed();
-    void cacheTableUseage(CUsedTablesBuilder & used, IHqlExpression * expr);
-
     void addAttribute(_ATOM name, IHqlExpression * value);
 
 public:
@@ -226,10 +229,6 @@ public:
     virtual StringBuffer &toString(StringBuffer &ret);
     virtual IHqlExpression *queryChild(unsigned idx) const;
     virtual unsigned numChildren() const ;
-    virtual bool isIndependentOfScope();
-    virtual bool usesSelector(IHqlExpression * selector);
-    virtual void gatherTablesUsed(CUsedTablesBuilder & used);
-    virtual void gatherTablesUsed(HqlExprCopyArray * newScope, HqlExprCopyArray * inScope);
 
     virtual ITypeInfo *queryRecordType();
     virtual IHqlExpression *queryRecord();
@@ -268,7 +267,29 @@ public:
     inline void resetTransformExtra(IInterface * _extra, unsigned depth);
 };
 
-class HQL_API CHqlExpressionWithType : public CHqlExpression
+class HQL_API CHqlExpressionWithTables : public CHqlExpression
+{
+public:
+    inline CHqlExpressionWithTables(node_operator op) : CHqlExpression(op) {}
+
+    virtual bool isIndependentOfScope();
+    virtual bool usesSelector(IHqlExpression * selector);
+    virtual void gatherTablesUsed(CUsedTablesBuilder & used);
+    virtual void gatherTablesUsed(HqlExprCopyArray * newScope, HqlExprCopyArray * inScope);
+
+protected:
+    void cacheChildrenTablesUsed(CUsedTablesBuilder & used, unsigned from, unsigned to);
+    void cacheInheritChildTablesUsed(IHqlExpression * ds, CUsedTablesBuilder & used, const HqlExprCopyArray & childInScopeTables);
+    void cachePotentialTablesUsed(CUsedTablesBuilder & used);
+    void cacheTablesProcessChildScope(CUsedTablesBuilder & used);
+    void cacheTablesUsed();
+    void cacheTableUseage(CUsedTablesBuilder & used, IHqlExpression * expr);
+
+protected:
+    CUsedTables usedTables;
+};
+
+class HQL_API CHqlExpressionWithType : public CHqlExpressionWithTables
 {
     friend HQL_API IHqlExpression *createOpenValue(node_operator op, ITypeInfo *type);
 public:
@@ -280,7 +301,8 @@ public:
     virtual IHqlExpression *clone(HqlExprArray &newkids);
 
 protected:
-    CHqlExpressionWithType(node_operator op, ITypeInfo *type);
+    inline CHqlExpressionWithType(node_operator op, ITypeInfo * _type) : CHqlExpressionWithTables(op), type(_type) {}
+    
     CHqlExpressionWithType(node_operator op, ITypeInfo *type, HqlExprArray & ownedOperands);
     ~CHqlExpressionWithType();
 
@@ -320,6 +342,11 @@ public:
     virtual ITypeInfo *queryType() const;
     virtual ITypeInfo *getType();
 
+    virtual bool isIndependentOfScope();
+    virtual bool usesSelector(IHqlExpression * selector);
+    virtual void gatherTablesUsed(CUsedTablesBuilder & used);
+    virtual void gatherTablesUsed(HqlExprCopyArray * newScope, HqlExprCopyArray * inScope);
+
     virtual void calcNormalized() = 0;
 
 protected:
@@ -1230,6 +1257,11 @@ public:
     virtual IValue *queryValue() const { return val; }
     virtual ITypeInfo *queryType() const;
     virtual ITypeInfo *getType();
+
+    virtual bool isIndependentOfScope() { return true; }
+    virtual bool usesSelector(IHqlExpression * selector) { return false; }
+    virtual void gatherTablesUsed(CUsedTablesBuilder & used) {}
+    virtual void gatherTablesUsed(HqlExprCopyArray * newScope, HqlExprCopyArray * inScope) {}
 };
 
 class CHqlParameter : public CHqlExpressionWithType
@@ -1348,7 +1380,7 @@ public:
     virtual StringBuffer &printAliases(StringBuffer &s, unsigned, bool &) { return s; }
 };
 
-class CHqlAttribute : public CHqlExpression
+class CHqlAttribute : public CHqlExpressionWithTables
 {
 protected:
     _ATOM name;
@@ -1402,7 +1434,7 @@ public:
     virtual StringBuffer &printAliases(StringBuffer &s, unsigned, bool &) { return s; }
 };
 
-class CHqlCachedBoundFunction : public CHqlExpression
+class CHqlCachedBoundFunction : public CHqlExpressionWithTables
 {
 public:
     CHqlCachedBoundFunction(IHqlExpression * func, bool _forceOutOfLineExpansion);
@@ -1415,7 +1447,7 @@ public:
     LinkedHqlExpr bound;
 };
 
-class CHqlRecord: public CHqlExpression, implements ITypeInfo, implements IHqlSimpleScope
+class CHqlRecord: public CHqlExpressionWithTables, implements ITypeInfo, implements IHqlSimpleScope
 {
 private:
     FieldTable fields;
@@ -1523,7 +1555,7 @@ public:
 };
 
 
-class CHqlAlienType : public CHqlExpression, implements ITypeInfo, implements IHqlSimpleScope, implements IHqlAlienTypeInfo
+class CHqlAlienType : public CHqlExpressionWithTables, implements ITypeInfo, implements IHqlSimpleScope, implements IHqlAlienTypeInfo
 {
 private:
     IHqlScope *scope;