Browse Source

HPCC-8835 Generate shared global classes instead of member classes

Signed-off-by: Shamser Ahmed <shamser.ahmed@lexisnexis.co.uk>
Shamser Ahmed 8 years ago
parent
commit
13c6d2811a

+ 1 - 0
ecl/hqlcpp/hqlcpp.cpp

@@ -1806,6 +1806,7 @@ void HqlCppTranslator::cacheOptions()
         DebugOption(options.translateDFSlayouts,"translateDFSlayouts", false),
         DebugOption(options.timeTransforms,"timeTransforms", false),
         DebugOption(options.reportDFSinfo,"reportDFSinfo", 0),
+        DebugOption(options.useGlobalCompareClass,"useGlobalCompareClass", false),
     };
 
     //get options values from workunit

+ 4 - 1
ecl/hqlcpp/hqlcpp.ipp

@@ -790,6 +790,7 @@ struct HqlCppOptions
     bool                addLikelihoodToGraph;
     bool                translateDFSlayouts;
     bool                timeTransforms;
+    bool                useGlobalCompareClass;
 };
 
 //Any information gathered while processing the query should be moved into here, rather than cluttering up the translator class
@@ -1009,6 +1010,7 @@ public:
     inline ErrorSeverityMapper & queryLocalOnWarningMapper() { return *localOnWarnings; }
 
     unsigned getConsistentUID(IHqlExpression * ptr);
+    unsigned getNextGlobalCompareId();
     bool insideOnCreate(BuildCtx & ctx);
     bool insideOnStart(BuildCtx & ctx);
     bool tempRowRequiresFinalize(IHqlExpression * record) const;
@@ -1672,7 +1674,7 @@ public:
 
     void buildActivityFramework(ActivityInstance * instance);
     void buildActivityFramework(ActivityInstance * instance, bool alwaysExecuted);      // called for all actions
-    void buildCompareClass(BuildCtx & ctx, const char * name, IHqlExpression * sortList, const DatasetReference & dataset);
+    void buildCompareClass(BuildCtx & ctx, const char * name, IHqlExpression * sortList, const DatasetReference & dataset, StringBuffer & compareFuncName);
     void buildCompareClass(BuildCtx & ctx, const char * name, IHqlExpression * orderExpr, IHqlExpression * datasetLeft, IHqlExpression * datasetRight, IHqlExpression * selSeq);
     void buildCompareMemberLR(BuildCtx & ctx, const char * name, IHqlExpression * orderExpr, IHqlExpression * datasetLeft, IHqlExpression * datasetRight, IHqlExpression * selSeq);
     void buildCompareMember(BuildCtx & ctx, const char * name, IHqlExpression * cond, const DatasetReference & dataset);
@@ -2019,6 +2021,7 @@ protected:
     unsigned            nextFieldId;
     unsigned            curWfid;
     unsigned            implicitFunctionId = 0;
+    unsigned            nextGlobalCompareId = 1;
     HqlExprArray        internalFunctions;
     HqlExprArray        internalFunctionExternals;
     UniqueSequenceCounter spillSequence;

+ 80 - 24
ecl/hqlcpp/hqlhtcpp.cpp

@@ -1389,6 +1389,12 @@ unsigned HqlCppTranslator::getConsistentUID(IHqlExpression * ptr)
 }
 
 
+unsigned HqlCppTranslator::getNextGlobalCompareId()
+{
+    return nextGlobalCompareId++;
+}
+
+
 unsigned HqlCppTranslator::beginFunctionGetCppIndex(unsigned activityId, bool isChildActivity)
 {
     activitiesThisCpp++;
@@ -5644,22 +5650,57 @@ void HqlCppTranslator::buildHashClass(BuildCtx & ctx, const char * name, IHqlExp
     endNestedClass(classStmt);
 }
 
-
-void HqlCppTranslator::buildCompareClass(BuildCtx & ctx, const char * name, IHqlExpression * sortList, const DatasetReference & dataset)
+void HqlCppTranslator::buildCompareClass(BuildCtx & ctx, const char * name, IHqlExpression * sortList, const DatasetReference & dataset, StringBuffer & compareFuncName)
 {
-    BuildCtx comparectx(ctx);
-    IHqlStmt * classStmt = beginNestedClass(comparectx, name, "ICompare");
-
+    if (options.useGlobalCompareClass)
     {
-        MemberFunction func(*this, comparectx, "virtual int docompare(const void * _left, const void * _right) const" OPTIMIZE_FUNCTION_ATTRIBUTE);
+        BuildCtx buildctx(*code, declareAtom);
+        GlobalCompareClass gcc(*this, sortList, dataset);
+
+        // stop duplicate classes being generated.
+        OwnedHqlExpr search = gcc.getUniqueKey();
+        HqlExprAssociation * match = buildctx.queryMatchExpr(search);
+        if (match)
+        {
+            match->queryExpr()->toString(compareFuncName);
+            return;
+        }
+
+        gcc.createGlobalCompareInstance(buildctx, name);
+        if (options.spanMultipleCpp)
+        {
+            BuildCtx declarectx(*code, declareAtom);
+            compareFuncName.set(gcc.createAccessFunction(declarectx));
+        }
+        else
+            compareFuncName.set(gcc.queryInstanceName());
+        MemberFunction func(*this, buildctx, "virtual int docompare(const void * _left, const void * _right) const" OPTIMIZE_FUNCTION_ATTRIBUTE);
         func.ctx.addQuotedLiteral("const unsigned char * left = (const unsigned char *) _left;");
         func.ctx.addQuotedLiteral("const unsigned char * right = (const unsigned char *) _right;");
         func.ctx.associateExpr(constantMemberMarkerExpr, constantMemberMarkerExpr);
 
         buildReturnOrder(func.ctx, sortList, dataset);
+
+        OwnedHqlExpr temp = createVariable(compareFuncName, makeVoidType());
+        buildctx.associateExpr(search, temp);
     }
+    else
+    {
+        BuildCtx comparectx(ctx);
+        IHqlStmt * classStmt = beginNestedClass(comparectx, name, "ICompare");
 
-    endNestedClass(classStmt);
+        {
+            MemberFunction func(*this, comparectx, "virtual int docompare(const void * _left, const void * _right) const" OPTIMIZE_FUNCTION_ATTRIBUTE);
+            func.ctx.addQuotedLiteral("const unsigned char * left = (const unsigned char *) _left;");
+            func.ctx.addQuotedLiteral("const unsigned char * right = (const unsigned char *) _right;");
+            func.ctx.associateExpr(constantMemberMarkerExpr, constantMemberMarkerExpr);
+
+            buildReturnOrder(func.ctx, sortList, dataset);
+        }
+
+        endNestedClass(classStmt);
+        compareFuncName.set(name);
+    }
 }
 
 
@@ -8448,10 +8489,14 @@ ABoundActivity * HqlCppTranslator::doBuildActivityMerge(BuildCtx & ctx, IHqlExpr
     if (sorts.ordinality() != 0)
     {
         OwnedHqlExpr sortOrder = createValueSafe(no_sortlist, makeSortListType(NULL), sorts);
-        instance->startctx.addQuotedLiteral("virtual ICompare * queryCompare() { return &compare; }");
 
         DatasetReference dsRef(dataset, no_activetable, NULL);
-        buildCompareClass(instance->nestedctx, "compare", sortOrder, dsRef);
+
+        StringBuffer compareClassInstance;
+        buildCompareClass(instance->nestedctx, "compare", sortOrder, dsRef, compareClassInstance);
+        MemberFunction func(*this, instance->startctx, "virtual ICompare * queryCompare()");
+        func.ctx.addReturnAddressOf(compareClassInstance);
+
         if (!instance->isLocal)
             generateSerializeKey(instance->nestedctx, no_none, dsRef, sorts, !instance->isChildActivity(), true);
     }
@@ -10484,10 +10529,12 @@ ABoundActivity * HqlCppTranslator::doBuildActivityOutputIndex(BuildCtx & ctx, IH
             HqlExprArray sorts;
             gatherIndexBuildSortOrder(sorts, expr, options.sortIndexPayload);
             OwnedHqlExpr sortOrder = createValueSafe(no_sortlist, makeSortListType(NULL), sorts);
-            instance->startctx.addQuotedLiteral("virtual ICompare * queryCompare() { return &compare; }");
 
             DatasetReference dsRef(dataset);
-            buildCompareClass(instance->nestedctx, "compare", sortOrder, dsRef);
+            StringBuffer compareClassInstance;
+            buildCompareClass(instance->nestedctx, "compare", sortOrder, dsRef, compareClassInstance);
+            MemberFunction func(*this, instance->startctx, "virtual ICompare * queryCompare()");
+            func.ctx.addReturnAddressOf(compareClassInstance);
         }
     }
     buildInstanceSuffix(instance);
@@ -14307,8 +14354,10 @@ ABoundActivity * HqlCppTranslator::doBuildActivityDedup(BuildCtx & ctx, IHqlExpr
     if (info.keepBest)
     {
         IHqlExpression * sortOrder = expr->queryAttribute(bestAtom)->queryChild(0);
-        buildCompareClass(instance->startctx, "bestCompare", sortOrder, DatasetReference(dataset));
-        instance->startctx.addQuotedLiteral("virtual ICompare * queryCompareBest() { return &bestCompare; }");
+        StringBuffer compareClassInstance;
+        buildCompareClass(instance->startctx, "bestCompare", sortOrder, DatasetReference(dataset), compareClassInstance);
+        MemberFunction func(*this, instance->startctx, "virtual ICompare * queryCompareBest()");
+        func.ctx.addReturnAddressOf(compareClassInstance);
     }
 
     buildInstanceSuffix(instance);
@@ -14353,10 +14402,13 @@ ABoundActivity * HqlCppTranslator::doBuildActivityDistribute(BuildCtx & ctx, IHq
         unwindChildren(sorts, cond);
 
         OwnedHqlExpr sortOrder = createValueSafe(no_sortlist, makeSortListType(NULL), sorts);
-        instance->startctx.addQuotedLiteral("virtual ICompare * queryCompare() { return &compare; }");
 
         DatasetReference dsRef(dataset);
-        buildCompareClass(instance->nestedctx, "compare", sortOrder, dsRef);
+        StringBuffer compareClassInstance;
+        buildCompareClass(instance->nestedctx, "compare", sortOrder, dsRef, compareClassInstance);
+        MemberFunction func(*this, instance->startctx, "virtual ICompare * queryCompare()");
+        func.ctx.addReturnAddressOf(compareClassInstance);
+
         if (!instance->isLocal)
             generateSerializeKey(instance->nestedctx, no_none, dsRef, sorts, true, true);
 
@@ -16630,10 +16682,11 @@ ABoundActivity * HqlCppTranslator::doBuildActivitySort(BuildCtx & ctx, IHqlExpre
     StringBuffer s;
     buildInstancePrefix(instance);
 
-    instance->classctx.addQuotedLiteral("virtual ICompare * queryCompare() { return &compare; }");
-
 //  sortlist.setown(spotScalarCSE(sortlist));
-    buildCompareClass(instance->nestedctx, "compare", sortlist, DatasetReference(dataset));
+    StringBuffer compareClassInstance;
+    buildCompareClass(instance->nestedctx, "compare", sortlist, DatasetReference(dataset), compareClassInstance);
+    MemberFunction func(*this, instance->classctx, "virtual ICompare * queryCompare()");
+    func.ctx.addReturnAddressOf(compareClassInstance);
 
     IHqlExpression * record = dataset->queryRecord();
     IAtom * serializeType = diskAtom; //MORE: Does this place a dependency on the implementation?
@@ -16642,8 +16695,6 @@ ABoundActivity * HqlCppTranslator::doBuildActivitySort(BuildCtx & ctx, IHqlExpre
     {
         if (record != serializedRecord)
         {
-            instance->classctx.addQuotedLiteral("virtual ICompare * queryCompareSerializedRow() { return &compareSR; }");
-
             OwnedHqlExpr selSeq = createSelectorSequence();
             OwnedHqlExpr leftSelector = createSelector(no_left, dataset, selSeq);
             OwnedHqlExpr mappedSortlist = replaceSelector(sortlist, dataset, leftSelector);
@@ -16652,7 +16703,11 @@ ABoundActivity * HqlCppTranslator::doBuildActivitySort(BuildCtx & ctx, IHqlExpre
             DatasetReference serializedRef(serializedDataset, no_left, selSeq);
             try
             {
-                buildCompareClass(instance->nestedctx, "compareSR", serializedSortlist, serializedRef);
+                StringBuffer compareClassInstance2;
+                buildCompareClass(instance->nestedctx, "compareSR", serializedSortlist, serializedRef, compareClassInstance);
+                MemberFunction func(*this, instance->classctx, "virtual ICompare * queryCompareSerializedRow()");
+                func.ctx.addReturnAddressOf(compareClassInstance);
+
             }
             catch (IException * e)
             {
@@ -16812,9 +16867,10 @@ ABoundActivity * HqlCppTranslator::doBuildActivityQuantile(BuildCtx & ctx, IHqlE
     IHqlExpression * dedupAttr = expr->queryAttribute(dedupAtom);
     IHqlExpression * range = queryAttributeChild(expr, rangeAtom, 0);
 
-    instance->classctx.addQuotedLiteral("virtual ICompare * queryCompare() { return &compare; }");
-
-    buildCompareClass(instance->nestedctx, "compare", sortlist, DatasetReference(dataset));
+    StringBuffer compareClassInstance;
+    buildCompareClass(instance->nestedctx, "compare", sortlist, DatasetReference(dataset), compareClassInstance);
+    MemberFunction func(*this, instance->classctx, "virtual ICompare * queryCompare()");
+    func.ctx.addReturnAddressOf(compareClassInstance);
 
     doBuildUnsigned64Function(instance->startctx, "getNumDivisions", number);
 

+ 42 - 0
ecl/hqlcpp/hqlhtcpp.ipp

@@ -58,6 +58,48 @@ private:
     bool grouped;
 };
 
+class GlobalCompareClass
+{
+public:
+    GlobalCompareClass(HqlCppTranslator & _translator,
+                       IHqlExpression * sortList,
+                       const DatasetReference & dataset) : translator(_translator)
+    {
+        IHqlExpression *rec = dataset.queryDataset()->queryRecord();
+        searchKey.setown(createAttribute(noSortAtom, LINK(sortList), LINK(rec)));
+    }
+    void createGlobalCompareInstance(BuildCtx & ctx, const char * name)
+    {
+        StringBuffer s, endText;
+        unsigned id = translator.getNextGlobalCompareId();
+        instanceName.set(s.set(name).append(id));
+        className.set(s.set("CCompare").append(id));
+
+        s.set("struct ").append(className).append(" : public ICompare");
+        endText.append(" ").append(instanceName).append(";");
+        ctx.addQuotedCompound(s,endText);
+    }
+    const char * createAccessFunction(BuildCtx & ctx)
+    {
+        StringBuffer temp;
+        translator.createAccessFunctions(temp, ctx,  BuildCtx::NormalPrio, "ICompare", instanceName);
+        temp.append("()");
+        instanceAccessorFuncName.set(temp);
+        return instanceAccessorFuncName;
+    }
+
+    const char * queryInstanceName()          { return instanceName; }
+    const char * queryAccessorFunctionName()  { return instanceAccessorFuncName; };
+    IHqlExpression * getUniqueKey()           { return searchKey.getLink(); }
+private:
+    HqlCppTranslator & translator;
+    HqlExprAttr      searchKey;
+    StringAttr       instanceName;
+    StringAttr       className;
+    StringAttr       instanceAccessorFuncName;
+};
+
+
 //===========================================================================
 
 class SteppingFieldSelection

+ 13 - 7
ecl/hqlcpp/hqlstep.cpp

@@ -828,11 +828,13 @@ ABoundActivity * HqlCppTranslator::doBuildActivityNWayMerge(BuildCtx & ctx, IHql
     buildInstancePrefix(instance);
 
     IHqlExpression * sortOrder = expr->queryChild(1);
-    instance->startctx.addQuotedLiteral("virtual ICompare * queryCompare() { return &compare; }");
 
     //NOTE: left is used instead of dataset in sort list
-    DatasetReference dsRef(dataset, no_left, querySelSeq(expr));        
-    buildCompareClass(instance->nestedctx, "compare", sortOrder, dsRef);
+    DatasetReference dsRef(dataset, no_left, querySelSeq(expr));
+    StringBuffer compareClassInstance;
+    buildCompareClass(instance->nestedctx, "compare", sortOrder, dsRef, compareClassInstance);
+    MemberFunction func(*this, instance->startctx, "virtual ICompare * queryCompare()");
+    func.ctx.addReturnAddressOf(compareClassInstance);
 
     if (expr->hasAttribute(dedupAtom))
         doBuildBoolFunction(instance->classctx, "dedup", true);
@@ -931,8 +933,10 @@ ABoundActivity * HqlCppTranslator::doBuildActivityNWayMergeJoin(BuildCtx & ctx,
 
     //virtual ICompare * queryEqualCompare()
     {
-        buildCompareClass(instance->nestedctx, "equalCompare", equalityList, leftRef);
-        instance->classctx.addQuotedLiteral("virtual ICompare * queryEqualCompare() { return &equalCompare; }");
+        StringBuffer compareClassInstance;
+        buildCompareClass(instance->nestedctx, "equalCompare", equalityList, leftRef, compareClassInstance);
+        MemberFunction func(*this, instance->classctx, "virtual ICompare * queryEqualCompare()");
+        func.ctx.addReturnAddressOf(compareClassInstance);
     }
 
     //virtual ICompareEq * queryExactCompare()
@@ -970,8 +974,10 @@ ABoundActivity * HqlCppTranslator::doBuildActivityNWayMergeJoin(BuildCtx & ctx,
     //NOTE: left is used instead of dataset in sort list
     //virtual ICompare * queryMergeCompare()
     {
-        buildCompareClass(instance->nestedctx, "mergeCompare", sortOrder, leftRef);
-        instance->classctx.addQuotedLiteral("virtual ICompare * queryMergeCompare() { return &mergeCompare; }");
+        StringBuffer compareClassInstance;
+        buildCompareClass(instance->nestedctx, "mergeCompare", sortOrder, leftRef, compareClassInstance);
+        MemberFunction func(*this, instance->classctx, "virtual ICompare * queryMergeCompare()");
+        func.ctx.addReturnAddressOf(compareClassInstance);
     }
 
     if (createClearRow)

+ 7 - 0
ecl/hqlcpp/hqlstmt.cpp

@@ -336,6 +336,13 @@ IHqlStmt * BuildCtx::addReturn(IHqlExpression * value)
     return appendSimple(next);
 }
 
+IHqlStmt * BuildCtx::addReturnAddressOf(const char * varname)
+{
+    StringBuffer s;
+    s.append("return &").append(varname).append(";");
+    return addQuoted(s);
+}
+
 IHqlStmt * BuildCtx::addFilter(IHqlExpression * condition)
 {
     HqlCompoundStmt * next = new HqlCompoundStmt(filter_stmt, curStmts);

+ 1 - 0
ecl/hqlcpp/hqlstmt.hpp

@@ -110,6 +110,7 @@ public:
     IHqlStmt *                  addExpr(IHqlExpression * condition);
     IHqlStmt *                  addExprOwn(IHqlExpression * condition);
     IHqlStmt *                  addReturn(IHqlExpression * value);
+    IHqlStmt *                  addReturnAddressOf(const char * varname);
     IHqlStmt *                  addFilter(IHqlExpression * condition);
     IHqlStmt *                  addFunction(IHqlExpression * funcdef);
     IHqlStmt *                  addGoto(const char * labelText);