Browse Source

Optimize some representations of no_select

The vast majority of the no_select expressions are stored
as the normalized form.  Using a different calss for these saves
8 bytes for a common case.

Signed-off-by: Gavin Halliday <gavin.halliday@lexisnexis.com>
Gavin Halliday 13 years ago
parent
commit
1cdaf6c932
2 changed files with 85 additions and 27 deletions
  1. 60 24
      ecl/hql/hqlexpr.cpp
  2. 25 3
      ecl/hql/hqlexpr.ipp

+ 60 - 24
ecl/hql/hqlexpr.cpp

@@ -5158,25 +5158,25 @@ IHqlExpression * CHqlExpression::calcNormalizedSelector() const
 
 //==============================================================================================================
 
-CHqlSelectExpression::CHqlSelectExpression()
+CHqlSelectBaseExpression::CHqlSelectBaseExpression()
 : CHqlExpression(no_select)
 {
 }
 
-ITypeInfo *CHqlSelectExpression::queryType() const
+ITypeInfo *CHqlSelectBaseExpression::queryType() const
 {
     dbgassertex(operands.ordinality()>=2);
     return operands.item(1).queryType();
 }
 
-ITypeInfo *CHqlSelectExpression::getType()
+ITypeInfo *CHqlSelectBaseExpression::getType()
 {
     dbgassertex(operands.ordinality()>=2);
     return operands.item(1).getType();
 }
 
 
-void CHqlSelectExpression::setOperands(IHqlExpression * left, IHqlExpression * right, IHqlExpression * attr)
+void CHqlSelectBaseExpression::setOperands(IHqlExpression * left, IHqlExpression * right, IHqlExpression * attr)
 {
     //Need to be very careful about the order that this is done in, since queryType() depends on operand2
     unsigned max = attr ? 3 : 2;
@@ -5189,52 +5189,88 @@ void CHqlSelectExpression::setOperands(IHqlExpression * left, IHqlExpression * r
     for (unsigned i=0; i < max; i++)
         onAppendOperand(operands.item(i), i);
 
-    normalized.setown(calcNormalizedSelector());
 }
 
-void CHqlSelectExpression::setOperands(HqlExprArray & _ownedOperands)
+void CHqlSelectBaseExpression::setOperands(HqlExprArray & _ownedOperands)
 {
     //base setOperands() already processes things in the correct order
     CHqlExpression::setOperands(_ownedOperands);
-    normalized.setown(calcNormalizedSelector());
 }
 
-IHqlExpression * CHqlSelectExpression::clone(HqlExprArray &newkids)
+IHqlExpression * CHqlSelectBaseExpression::clone(HqlExprArray &newkids)
 {
     return createSelectExpr(newkids);
 }
 
-IHqlExpression * CHqlSelectExpression::queryNormalizedSelector(bool skipIndex)
-{
-    if (normalized)
-        return normalized;
-    return this;
-}
-
-IHqlExpression * CHqlSelectExpression::makeSelectExpression(IHqlExpression * left, IHqlExpression * right, IHqlExpression * attr)
+IHqlExpression * CHqlSelectBaseExpression::makeSelectExpression(IHqlExpression * left, IHqlExpression * right, IHqlExpression * attr)
 {
 #ifdef _DEBUG
     assertex(!right->isDataset());
     assertex(left->getOperator() != no_activerow);
 #endif
-    CHqlSelectExpression * select = new CHqlSelectExpression;
+    IHqlExpression * normalizedLeft = left->queryNormalizedSelector();
+    bool needNormalize = (normalizedLeft != left) || (attr && attr->queryName() == newAtom);
+
+    CHqlSelectBaseExpression * select;
+    if (needNormalize)
+        select = new CHqlSelectExpression;
+    else
+        select = new CHqlNormalizedSelectExpression;
     select->setOperands(left, right, attr);
+    select->calcNormalized();
     return select->closeExpr();
 }
 
-IHqlExpression * CHqlSelectExpression::makeSelectExpression(HqlExprArray & _ownedOperands)
+IHqlExpression * CHqlSelectBaseExpression::makeSelectExpression(HqlExprArray & ownedOperands)
 {
 #ifdef _DEBUG
-    assertex(!_ownedOperands.item(1).isDataset());
-    assertex(_ownedOperands.item(0).getOperator() != no_activerow);
+    assertex(!ownedOperands.item(1).isDataset());
+    assertex(ownedOperands.item(0).getOperator() != no_activerow);
 #endif
-    CHqlSelectExpression * select = new CHqlSelectExpression;
-    select->setOperands(_ownedOperands);
+    IHqlExpression * left = &ownedOperands.item(0);
+    IHqlExpression * normalizedLeft = left->queryNormalizedSelector();
+    bool needNormalize = (normalizedLeft != left) || ((ownedOperands.ordinality() > 2) && ::hasProperty(newAtom, ownedOperands));
+
+    CHqlSelectBaseExpression * select;
+    if (needNormalize)
+        select = new CHqlSelectExpression;
+    else
+        select = new CHqlNormalizedSelectExpression;
+    select->setOperands(ownedOperands);
+    select->calcNormalized();
     return select->closeExpr();
 }
 
 //==============================================================================================================
 
+IHqlExpression * CHqlNormalizedSelectExpression::queryNormalizedSelector(bool skipIndex)
+{
+    return this;
+}
+
+void CHqlNormalizedSelectExpression::calcNormalized()
+{
+#ifdef VERIFY_EXPR_INTEGRITY
+    OwnedHqlExpr normalized = calcNormalizedSelector();
+    assertex(!normalized);
+#endif
+}
+
+IHqlExpression * CHqlSelectExpression::queryNormalizedSelector(bool skipIndex)
+{
+    if (normalized)
+        return normalized;
+    return this;
+}
+
+void CHqlSelectExpression::calcNormalized()
+{
+    normalized.setown(calcNormalizedSelector());
+    assertex(normalized);
+}
+
+//==============================================================================================================
+
 CHqlConstant::CHqlConstant(IValue *_val) : CHqlExpression(no_constant)
 {
     val = _val;
@@ -11960,7 +11996,7 @@ extern IHqlExpression * createSelectExpr(IHqlExpression * _lhs, IHqlExpression *
     if (t == type_row)
         return createRow(no_select, LINK(normalLhs), createComma(rhs, LINK(newAttr)));
 
-    return CHqlSelectExpression::makeSelectExpression(LINK(normalLhs), rhs, LINK(newAttr));
+    return CHqlSelectBaseExpression::makeSelectExpression(LINK(normalLhs), rhs, LINK(newAttr));
 }
 
 static IHqlExpression * doCreateSelectExpr(HqlExprArray & args)
@@ -11974,7 +12010,7 @@ static IHqlExpression * doCreateSelectExpr(HqlExprArray & args)
     if (t == type_row)
         return createRow(no_select, args);
 
-    return CHqlSelectExpression::makeSelectExpression(args);
+    return CHqlSelectBaseExpression::makeSelectExpression(args);
 }
 
 extern IHqlExpression * createSelectExpr(HqlExprArray & args)

+ 25 - 3
ecl/hql/hqlexpr.ipp

@@ -310,23 +310,45 @@ public:
 };
 
 
-class CHqlSelectExpression : public CHqlExpression
+class CHqlSelectBaseExpression : public CHqlExpression
 {
 public:
     static IHqlExpression * makeSelectExpression(IHqlExpression * left, IHqlExpression * right, IHqlExpression * attr);
     static IHqlExpression * makeSelectExpression(HqlExprArray & ownedOperands);
 
     virtual IHqlExpression *clone(HqlExprArray &newkids);
-    virtual IHqlExpression *queryNormalizedSelector(bool skipIndex);
     virtual ITypeInfo *queryType() const;
     virtual ITypeInfo *getType();
 
+    virtual void calcNormalized() = 0;
+
 protected:
-    CHqlSelectExpression();
+    CHqlSelectBaseExpression();
 
     void setOperands(IHqlExpression * left, IHqlExpression * right, IHqlExpression * attr);
     void setOperands(HqlExprArray & _ownedOperands);
+};
+
+class CHqlNormalizedSelectExpression : public CHqlSelectBaseExpression
+{
+    friend class CHqlSelectBaseExpression;
+public:
+    virtual IHqlExpression *queryNormalizedSelector(bool skipIndex);
+    virtual void calcNormalized();
 
+protected:
+    CHqlNormalizedSelectExpression() {}
+};
+
+class CHqlSelectExpression : public CHqlSelectBaseExpression
+{
+    friend class CHqlSelectBaseExpression;
+public:
+    virtual IHqlExpression *queryNormalizedSelector(bool skipIndex);
+    virtual void calcNormalized();
+
+protected:
+    CHqlSelectExpression() {}
 
 protected:
     HqlExprAttr normalized;