Created a new class to represent executable.

The new class represents executables created from shared objects,
which allows query exported fields, for each, etc.
This allows this functionality to be shared with other part of the
system besides CPU script, e.g., script groups.

Change-Id: I5223c329bdb70085eb1dce7aab5ec91626f579f4
diff --git a/cpu_ref/rsCpuScript.cpp b/cpu_ref/rsCpuScript.cpp
index 38a0bf5..7062cb4 100644
--- a/cpu_ref/rsCpuScript.cpp
+++ b/cpu_ref/rsCpuScript.cpp
@@ -469,12 +469,6 @@
 
     mScriptSO = nullptr;
 
-    mInvokeFunctions = nullptr;
-    mForEachFunctions = nullptr;
-    mFieldAddress = nullptr;
-    mFieldIsObject = nullptr;
-    mForEachSignatures = nullptr;
-
 #ifndef RS_COMPATIBILITY_LIB
     mCompilerDriver = nullptr;
 #endif
@@ -484,7 +478,7 @@
     mRootExpand = nullptr;
     mInit = nullptr;
     mFreeChildren = nullptr;
-
+    mScriptExec = nullptr;
 
     mBoundAllocs = nullptr;
     mIntrinsicData = nullptr;
@@ -492,12 +486,6 @@
 }
 
 bool RsdCpuScriptImpl::storeRSInfoFromSO() {
-    char line[MAXLINE];
-    size_t varCount = 0;
-    size_t funcCount = 0;
-    size_t forEachCount = 0;
-    size_t objectSlotCount = 0;
-
     mRoot = (RootFunc_t) dlsym(mScriptSO, "root");
     if (mRoot) {
         //ALOGE("Found root(): %p", mRoot);
@@ -515,186 +503,154 @@
         //ALOGE("Found .rs.dtor(): %p", mFreeChildren);
     }
 
-    const char *rsInfo = (const char *) dlsym(mScriptSO, ".rs.info");
-    if (rsInfo) {
-        //ALOGE("Found .rs.info(): %p - %s", rsInfo, rsInfo);
+    mScriptExec = ScriptExecutable::createFromSharedObject(
+            mCtx->getContext(), mScriptSO);
+
+    if (mScriptExec == nullptr) {
+        return false;
     }
 
-    if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
-        goto error;
-    }
-    if (sscanf(line, EXPORT_VAR_STR "%zu", &varCount) != 1) {
-        ALOGE("Invalid export var count!: %s", line);
-        goto error;
-    }
-
-    mExportedVariableCount = varCount;
-    //ALOGE("varCount: %zu", varCount);
-    if (varCount > 0) {
-        // Start by creating/zeroing this member, since we don't want to
-        // accidentally clean up invalid pointers later (if we error out).
-        mFieldIsObject = new bool[varCount];
-        if (mFieldIsObject == nullptr) {
-            goto error;
-        }
-        memset(mFieldIsObject, 0, varCount * sizeof(*mFieldIsObject));
-        mFieldAddress = new void*[varCount];
-        if (mFieldAddress == nullptr) {
-            goto error;
-        }
-        for (size_t i = 0; i < varCount; ++i) {
-            if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
-                goto error;
-            }
-            char *c = strrchr(line, '\n');
-            if (c) {
-                *c = '\0';
-            }
-            mFieldAddress[i] = dlsym(mScriptSO, line);
-            if (mFieldAddress[i] == nullptr) {
-                ALOGE("Failed to find variable address for %s: %s",
-                      line, dlerror());
-                // Not a critical error if we don't find a global variable.
-            }
-            else {
-                //ALOGE("Found variable %s at %p", line,
-                //mFieldAddress[i]);
-            }
-        }
-    }
-
-    if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
-        goto error;
-    }
-    if (sscanf(line, EXPORT_FUNC_STR "%zu", &funcCount) != 1) {
-        ALOGE("Invalid export func count!: %s", line);
-        goto error;
-    }
-
-    mExportedFunctionCount = funcCount;
-    //ALOGE("funcCount: %zu", funcCount);
-
-    if (funcCount > 0) {
-        mInvokeFunctions = new InvokeFunc_t[funcCount];
-        if (mInvokeFunctions == nullptr) {
-            goto error;
-        }
-        for (size_t i = 0; i < funcCount; ++i) {
-            if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
-                goto error;
-            }
-            char *c = strrchr(line, '\n');
-            if (c) {
-                *c = '\0';
-            }
-
-            mInvokeFunctions[i] = (InvokeFunc_t) dlsym(mScriptSO, line);
-            if (mInvokeFunctions[i] == nullptr) {
-                ALOGE("Failed to get function address for %s(): %s",
-                      line, dlerror());
-                goto error;
-            }
-            else {
-                //ALOGE("Found InvokeFunc_t %s at %p", line, mInvokeFunctions[i]);
-            }
-        }
-    }
-
-    if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
-        goto error;
-    }
-    if (sscanf(line, EXPORT_FOREACH_STR "%zu", &forEachCount) != 1) {
-        ALOGE("Invalid export forEach count!: %s", line);
-        goto error;
-    }
-
-    if (forEachCount > 0) {
-
-        mForEachSignatures = new uint32_t[forEachCount];
-        if (mForEachSignatures == nullptr) {
-            goto error;
-        }
-        mForEachFunctions = new ForEachFunc_t[forEachCount];
-        if (mForEachFunctions == nullptr) {
-            goto error;
-        }
-        for (size_t i = 0; i < forEachCount; ++i) {
-            unsigned int tmpSig = 0;
-            char tmpName[MAXLINE];
-
-            if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
-                goto error;
-            }
-            if (sscanf(line, "%u - %" MAKE_STR(MAXLINE) "s",
-                       &tmpSig, tmpName) != 2) {
-                ALOGE("Invalid export forEach!: %s", line);
-                goto error;
-            }
-
-            // Lookup the expanded ForEach kernel.
-            strncat(tmpName, ".expand", MAXLINE-1-strlen(tmpName));
-            mForEachSignatures[i] = tmpSig;
-            mForEachFunctions[i] =
-                    (ForEachFunc_t) dlsym(mScriptSO, tmpName);
-            if (i != 0 && mForEachFunctions[i] == nullptr) {
-                // Ignore missing root.expand functions.
-                // root() is always specified at location 0.
-                ALOGE("Failed to find forEach function address for %s: %s",
-                      tmpName, dlerror());
-                goto error;
-            }
-            else {
-                //ALOGE("Found forEach %s at %p", tmpName, mForEachFunctions[i]);
-            }
-        }
-    }
-
-    if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
-        goto error;
-    }
-    if (sscanf(line, OBJECT_SLOT_STR "%zu", &objectSlotCount) != 1) {
-        ALOGE("Invalid object slot count!: %s", line);
-        goto error;
-    }
-
-    if (objectSlotCount > 0) {
-        rsAssert(varCount > 0);
-        for (size_t i = 0; i < objectSlotCount; ++i) {
-            uint32_t varNum = 0;
-            if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
-                goto error;
-            }
-            if (sscanf(line, "%u", &varNum) != 1) {
-                ALOGE("Invalid object slot!: %s", line);
-                goto error;
-            }
-
-            if (varNum < varCount) {
-                mFieldIsObject[varNum] = true;
-            }
-        }
-    }
-
+    size_t varCount = mScriptExec->getExportedVariableCount();
     if (varCount > 0) {
         mBoundAllocs = new Allocation *[varCount];
         memset(mBoundAllocs, 0, varCount * sizeof(*mBoundAllocs));
     }
 
-    if (mScriptSO == (void*)1) {
-        //rsdLookupRuntimeStub(script, "acos");
+    return true;
+}
+
+ScriptExecutable* ScriptExecutable::createFromSharedObject(
+    Context* RSContext, void* sharedObj) {
+    char line[MAXLINE];
+
+    size_t varCount = 0;
+    size_t funcCount = 0;
+    size_t forEachCount = 0;
+    size_t objectSlotCount = 0;
+
+    const char *rsInfo = (const char *) dlsym(sharedObj, ".rs.info");
+
+    if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
+        return nullptr;
+    }
+    if (sscanf(line, EXPORT_VAR_STR "%zu", &varCount) != 1) {
+        ALOGE("Invalid export var count!: %s", line);
+        return nullptr;
     }
 
-    return true;
+    std::vector<void*> fieldAddress;
 
-error:
-    delete[] mInvokeFunctions;
-    delete[] mForEachFunctions;
-    delete[] mFieldAddress;
-    delete[] mFieldIsObject;
-    delete[] mForEachSignatures;
-    delete[] mBoundAllocs;
+    for (size_t i = 0; i < varCount; ++i) {
+        if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
+            return nullptr;
+        }
+        char *c = strrchr(line, '\n');
+        if (c) {
+            *c = '\0';
+        }
+        void* addr = dlsym(sharedObj, line);
+        if (addr == nullptr) {
+            ALOGE("Failed to find variable address for %s: %s",
+                  line, dlerror());
+            // Not a critical error if we don't find a global variable.
+        }
+        fieldAddress.push_back(addr);
+    }
 
-    return false;
+    if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
+        return nullptr;
+    }
+    if (sscanf(line, EXPORT_FUNC_STR "%zu", &funcCount) != 1) {
+        ALOGE("Invalid export func count!: %s", line);
+        return nullptr;
+    }
+
+    std::vector<InvokeFunc_t> invokeFunctions(funcCount);
+
+    for (size_t i = 0; i < funcCount; ++i) {
+        if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
+            return nullptr ;
+        }
+        char *c = strrchr(line, '\n');
+        if (c) {
+            *c = '\0';
+        }
+
+        invokeFunctions[i] = (InvokeFunc_t) dlsym(sharedObj, line);
+        if (invokeFunctions[i] == nullptr) {
+            ALOGE("Failed to get function address for %s(): %s",
+                  line, dlerror());
+            return nullptr;
+        }
+    }
+
+    if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
+        return nullptr;
+    }
+    if (sscanf(line, EXPORT_FOREACH_STR "%zu", &forEachCount) != 1) {
+        ALOGE("Invalid export forEach count!: %s", line);
+        return nullptr;
+    }
+
+    std::vector<ForEachFunc_t> forEachFunctions(forEachCount);
+    std::vector<uint32_t> forEachSignatures(forEachCount);
+
+    for (size_t i = 0; i < forEachCount; ++i) {
+        unsigned int tmpSig = 0;
+        char tmpName[MAXLINE];
+
+        if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
+            return nullptr;
+        }
+        if (sscanf(line, "%u - %" MAKE_STR(MAXLINE) "s",
+                   &tmpSig, tmpName) != 2) {
+          ALOGE("Invalid export forEach!: %s", line);
+          return nullptr;
+        }
+
+        // Lookup the expanded ForEach kernel.
+        strncat(tmpName, ".expand", MAXLINE-1-strlen(tmpName));
+        forEachSignatures[i] = tmpSig;
+        forEachFunctions[i] =
+            (ForEachFunc_t) dlsym(sharedObj, tmpName);
+        if (i != 0 && forEachFunctions[i] == nullptr) {
+            // Ignore missing root.expand functions.
+            // root() is always specified at location 0.
+            ALOGE("Failed to find forEach function address for %s: %s",
+                  tmpName, dlerror());
+            return nullptr;
+        }
+    }
+
+    if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
+        return nullptr;
+    }
+    if (sscanf(line, OBJECT_SLOT_STR "%zu", &objectSlotCount) != 1) {
+        ALOGE("Invalid object slot count!: %s", line);
+        return nullptr;
+    }
+
+    std::vector<bool> fieldIsObject(varCount, false);
+
+    rsAssert(varCount > 0);
+    for (size_t i = 0; i < objectSlotCount; ++i) {
+        uint32_t varNum = 0;
+        if (strgets(line, MAXLINE, &rsInfo) == nullptr) {
+            return nullptr;
+        }
+        if (sscanf(line, "%u", &varNum) != 1) {
+            ALOGE("Invalid object slot!: %s", line);
+            return nullptr;
+        }
+
+        if (varNum < varCount) {
+            fieldIsObject[varNum] = true;
+        }
+    }
+
+    return new ScriptExecutable(
+        RSContext, fieldAddress, fieldIsObject, invokeFunctions,
+        forEachFunctions, forEachSignatures);
 }
 
 bool RsdCpuScriptImpl::init(char const *resName, char const *cacheDir,
@@ -851,8 +807,8 @@
 
 void RsdCpuScriptImpl::populateScript(Script *script) {
     // Copy info over to runtime
-    script->mHal.info.exportedFunctionCount = mExportedFunctionCount;
-    script->mHal.info.exportedVariableCount = mExportedVariableCount;
+    script->mHal.info.exportedFunctionCount = mScriptExec->getExportedFunctionCount();
+    script->mHal.info.exportedVariableCount = mScriptExec->getExportedVariableCount();
     script->mHal.info.exportedPragmaCount = 0;
     script->mHal.info.exportedPragmaKeyList = 0;
     script->mHal.info.exportedPragmaValueList = 0;
@@ -1025,9 +981,9 @@
 void RsdCpuScriptImpl::forEachKernelSetup(uint32_t slot, MTLaunchStruct *mtls) {
     mtls->script = this;
     mtls->fep.slot = slot;
-    mtls->kernel = reinterpret_cast<ForEachFunc_t>(mForEachFunctions[slot]);
+    mtls->kernel = mScriptExec->getForEachFunction(slot);
     rsAssert(mtls->kernel != nullptr);
-    mtls->sig = mForEachSignatures[slot];
+    mtls->sig = mScriptExec->getForEachSignature(slot);
 }
 
 int RsdCpuScriptImpl::invokeRoot() {
@@ -1070,7 +1026,7 @@
 
     RsdCpuScriptImpl * oldTLS = mCtx->setTLS(this);
     reinterpret_cast<void (*)(const void *, uint32_t)>(
-        mInvokeFunctions[slot])(ap? (const void *) ap: params, paramLength);
+        mScriptExec->getInvokeFunction(slot))(ap? (const void *) ap: params, paramLength);
 
     mCtx->setTLS(oldTLS);
 }
@@ -1084,7 +1040,7 @@
         //return;
     //}
 
-    int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
+    int32_t *destPtr = reinterpret_cast<int32_t *>(mScriptExec->getFieldAddress(slot));
     if (!destPtr) {
         //ALOGV("Calling setVar on slot = %i which is null", slot);
         return;
@@ -1097,7 +1053,7 @@
     //rsAssert(!script->mFieldIsObject[slot]);
     //ALOGE("getGlobalVar %i %p %zu", slot, data, dataLength);
 
-    int32_t *srcPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
+    int32_t *srcPtr = reinterpret_cast<int32_t *>(mScriptExec->getFieldAddress(slot));
     if (!srcPtr) {
         //ALOGV("Calling setVar on slot = %i which is null", slot);
         return;
@@ -1109,7 +1065,7 @@
 void RsdCpuScriptImpl::setGlobalVarWithElemDims(uint32_t slot, const void *data, size_t dataLength,
                                                 const Element *elem,
                                                 const uint32_t *dims, size_t dimLength) {
-    int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
+    int32_t *destPtr = reinterpret_cast<int32_t *>(mScriptExec->getFieldAddress(slot));
     if (!destPtr) {
         //ALOGV("Calling setVar on slot = %i which is null", slot);
         return;
@@ -1146,7 +1102,7 @@
     //rsAssert(!script->mFieldIsObject[slot]);
     //ALOGE("setGlobalBind %i %p", slot, data);
 
-    int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
+    int32_t *destPtr = reinterpret_cast<int32_t *>(mScriptExec->getFieldAddress(slot));
     if (!destPtr) {
         //ALOGV("Calling setVar on slot = %i which is null", slot);
         return;
@@ -1165,7 +1121,7 @@
     //rsAssert(script->mFieldIsObject[slot]);
     //ALOGE("setGlobalObj %i %p", slot, data);
 
-    int32_t *destPtr = reinterpret_cast<int32_t *>(mFieldAddress[slot]);
+    int32_t *destPtr = reinterpret_cast<int32_t *>(mScriptExec->getFieldAddress(slot));
     if (!destPtr) {
         //ALOGV("Calling setVar on slot = %i which is null", slot);
         return;
@@ -1176,30 +1132,14 @@
 
 RsdCpuScriptImpl::~RsdCpuScriptImpl() {
 #ifndef RS_COMPATIBILITY_LIB
-
     if (mCompilerDriver) {
         delete mCompilerDriver;
     }
-
 #endif
 
-    if (mFieldIsObject) {
-        for (size_t i = 0; i < mExportedVariableCount; ++i) {
-            if (mFieldIsObject[i]) {
-                if (mFieldAddress[i] != nullptr) {
-                    rs_object_base *obj_addr =
-                        reinterpret_cast<rs_object_base *>(mFieldAddress[i]);
-                    rsrClearObject(mCtx->getContext(), obj_addr);
-                }
-            }
-        }
+    if (mScriptExec != nullptr) {
+        delete mScriptExec;
     }
-
-    if (mInvokeFunctions) delete[] mInvokeFunctions;
-    if (mForEachFunctions) delete[] mForEachFunctions;
-    if (mFieldAddress) delete[] mFieldAddress;
-    if (mFieldIsObject) delete[] mFieldIsObject;
-    if (mForEachSignatures) delete[] mForEachSignatures;
     if (mBoundAllocs) delete[] mBoundAllocs;
     if (mScriptSO) {
         dlclose(mScriptSO);
diff --git a/cpu_ref/rsCpuScript.h b/cpu_ref/rsCpuScript.h
index 7f7750f..9cfc84f 100644
--- a/cpu_ref/rsCpuScript.h
+++ b/cpu_ref/rsCpuScript.h
@@ -21,12 +21,13 @@
 #include <rsRuntime.h>
 
 #ifndef RS_COMPATIBILITY_LIB
-#include <vector>
 #include <utility>
 #endif
 
 #include "rsCpuCore.h"
 
+#include <vector>
+
 namespace bcc {
     class BCCContext;
     class RSCompilerDriver;
@@ -39,7 +40,55 @@
 namespace android {
 namespace renderscript {
 
+class ScriptExecutable {
+ public:
+  ScriptExecutable(Context* RSContext,
+                   std::vector<void*>& fieldAddress,
+                   std::vector<bool>& fieldIsObject,
+                   std::vector<InvokeFunc_t>& invokeFunctions,
+                   std::vector<ForEachFunc_t>& forEachFunctions,
+                   std::vector<uint32_t>& forEachSignatures) : mRS(RSContext) {
+      mFieldAddress.swap(fieldAddress);
+      mFieldIsObject.swap(fieldIsObject);
+      mInvokeFunctions.swap(invokeFunctions);
+      mForEachFunctions.swap(forEachFunctions);
+      mForEachSignatures.swap(forEachSignatures);
+  }
 
+  ~ScriptExecutable() {
+      for (size_t i = 0; i < mFieldAddress.size(); ++i) {
+          if (mFieldIsObject[i]) {
+              if (mFieldAddress[i] != nullptr) {
+                  rs_object_base *obj_addr =
+                      reinterpret_cast<rs_object_base *>(mFieldAddress[i]);
+                  rsrClearObject(mRS, obj_addr);
+              }
+          }
+      }
+  }
+
+  static ScriptExecutable*
+  createFromSharedObject(Context* RSContext, void* sharedObj);
+
+  size_t getExportedVariableCount() const { return mFieldAddress.size(); }
+  size_t getExportedFunctionCount() const { return mInvokeFunctions.size(); }
+  size_t getExportedForEachCount() const { return mForEachFunctions.size(); }
+
+  void* getFieldAddress(int slot) const { return mFieldAddress[slot]; }
+  bool getFieldIsObject(int slot) const { return mFieldIsObject[slot]; }
+  InvokeFunc_t getInvokeFunction(int slot) const { return mInvokeFunctions[slot]; }
+  ForEachFunc_t getForEachFunction(int slot) const { return mForEachFunctions[slot]; }
+  uint32_t getForEachSignature(int slot) const { return mForEachSignatures[slot]; }
+
+ private:
+  std::vector<void*> mFieldAddress;
+  std::vector<bool> mFieldIsObject;
+  std::vector<InvokeFunc_t> mInvokeFunctions;
+  std::vector<ForEachFunc_t> mForEachFunctions;
+  std::vector<uint32_t> mForEachSignatures;
+
+  Context* mRS;
+};
 
 class RsdCpuScriptImpl : public RsdCpuReferenceImpl::CpuScript {
 public:
@@ -124,15 +173,7 @@
     RootFunc_t mRootExpand;
     InvokeFunc_t mInit;
     InvokeFunc_t mFreeChildren;
-    InvokeFunc_t *mInvokeFunctions;
-    ForEachFunc_t *mForEachFunctions;
-
-    void **mFieldAddress;
-    bool *mFieldIsObject;
-    uint32_t *mForEachSignatures;
-
-    size_t mExportedVariableCount;
-    size_t mExportedFunctionCount;
+    ScriptExecutable* mScriptExec;
 
     Allocation **mBoundAllocs;
     void * mIntrinsicData;
@@ -147,6 +188,7 @@
 
 
 }
+
 }
 
 #endif