Use build fingerprint and compile command for caching.

If either of those have changed, we need to invalidate the
compiled bit code.

Change-Id: Ic0c392ea5bfff5bf6dc8511740306895b1b12c82
diff --git a/cpu_ref/rsCpuScript.cpp b/cpu_ref/rsCpuScript.cpp
index 81e70f0..8350d00 100644
--- a/cpu_ref/rsCpuScript.cpp
+++ b/cpu_ref/rsCpuScript.cpp
@@ -216,29 +216,53 @@
 
 const static char *BCC_EXE_PATH = "/system/bin/bcc";
 
-static bool compileBitcode(const char *cacheDir,
-                           const char *resName,
+static void setCompileArguments(std::vector<const char*>* args, const android::String8& bcFileName,
+                                const char* cacheDir, const char* resName, const char* core_lib,
+                                bool useRSDebugContext, const char* bccPluginName) {
+    rsAssert(cacheDir && resName && core_lib);
+    args->push_back(BCC_EXE_PATH);
+    args->push_back("-o");
+    args->push_back(resName);
+    args->push_back("-output_path");
+    args->push_back(cacheDir);
+    args->push_back("-bclib");
+    args->push_back(core_lib);
+    args->push_back("-mtriple");
+    args->push_back(DEFAULT_TARGET_TRIPLE_STRING);
+
+    // Execute the bcc compiler.
+    if (useRSDebugContext) {
+        args->push_back("-rs-debug-ctx");
+    } else {
+        // Only load additional libraries for compiles that don't use
+        // the debug context.
+        if (bccPluginName && strlen(bccPluginName) > 0) {
+            args->push_back("-load");
+            args->push_back(bccPluginName);
+        }
+    }
+
+    args->push_back(bcFileName.string());
+    args->push_back(NULL);
+}
+
+static bool compileBitcode(const android::String8& bcFileName,
                            const char *bitcode,
                            size_t bitcodeSize,
-                           const char *core_lib,
-                           bool useRSDebugContext,
-                           const char *bccPluginName) {
-    rsAssert(cacheDir && resName && bitcode && bitcodeSize && core_lib);
+                           const char** compileArguments,
+                           const std::string& compileCommandLine) {
+    rsAssert(bitcode && bitcodeSize);
 
-    android::String8 bcFilename(cacheDir);
-    bcFilename.append("/");
-    bcFilename.append(resName);
-    bcFilename.append(".bc");
-    FILE *bcfile = fopen(bcFilename.string(), "w");
+    FILE *bcfile = fopen(bcFileName.string(), "w");
     if (!bcfile) {
-        ALOGE("Could not write to %s", bcFilename.string());
+        ALOGE("Could not write to %s", bcFileName.string());
         return false;
     }
     size_t nwritten = fwrite(bitcode, 1, bitcodeSize, bcfile);
     fclose(bcfile);
     if (nwritten != bitcodeSize) {
         ALOGE("Could not write %zu bytes to %s", bitcodeSize,
-              bcFilename.string());
+              bcFileName.string());
         return false;
     }
 
@@ -250,40 +274,9 @@
         return false;
     }
     case 0: {  // Child process
-        std::vector<std::string> args;
-        args.push_back(BCC_EXE_PATH);
-        args.push_back("-o");
-        args.push_back(resName);
-        args.push_back("-output_path");
-        args.push_back(cacheDir);
-        args.push_back("-bclib");
-        args.push_back(core_lib);
-        args.push_back("-mtriple");
-        args.push_back(DEFAULT_TARGET_TRIPLE_STRING);
+        ALOGV("Invoking BCC with: %s", compileCommandLine.c_str());
+        execv(BCC_EXE_PATH, (char* const*)compileArguments);
 
-        // Execute the bcc compiler.
-        if (useRSDebugContext) {
-            args.push_back("-rs-debug-ctx");
-        } else {
-            // Only load additional libraries for compiles that don't use
-            // the debug context.
-            if (bccPluginName && strlen(bccPluginName) > 0) {
-                args.push_back("-load");
-                args.push_back(bccPluginName);
-            }
-        }
-
-        args.push_back(bcFilename.string());
-
-        const char **cargs = new const char *[args.size() + 1];
-        for (uint32_t i = 0; i < args.size(); i++) {
-            cargs[i] = args[i].c_str();
-        }
-        cargs[args.size()] = NULL;
-
-        execv(BCC_EXE_PATH, (char *const *)cargs);
-
-        delete [] cargs;
         ALOGE("execv() failed: %s", strerror(errno));
         abort();
         return false;
@@ -318,13 +311,9 @@
 #define MAKE_STR_HELPER(S) #S
 #define MAKE_STR(S) MAKE_STR_HELPER(S)
 #define EXPORT_VAR_STR "exportVarCount: "
-#define EXPORT_VAR_STR_LEN strlen(EXPORT_VAR_STR)
 #define EXPORT_FUNC_STR "exportFuncCount: "
-#define EXPORT_FUNC_STR_LEN strlen(EXPORT_FUNC_STR)
 #define EXPORT_FOREACH_STR "exportForEachCount: "
-#define EXPORT_FOREACH_STR_LEN strlen(EXPORT_FOREACH_STR)
 #define OBJECT_SLOT_STR "objectSlotCount: "
-#define OBJECT_SLOT_STR_LEN strlen(OBJECT_SLOT_STR)
 
 // Copy up to a newline or size chars from str -> s, updating str
 // Returns s when successful and NULL when '\0' is finally reached.
@@ -390,7 +379,6 @@
 
     mCtx->lockMutex();
 #ifndef RS_COMPATIBILITY_LIB
-    bcc::RSExecutable *exec = NULL;
     bool useRSDebugContext = false;
 
     mCompilerContext = NULL;
@@ -424,63 +412,79 @@
         setupCompilerCallback(mCompilerDriver);
     }
 
-    bcinfo::MetadataExtractor ME((const char *) bitcode, bitcodeSize);
-    if (!ME.extract()) {
+    bcinfo::MetadataExtractor bitcodeMetadata((const char *) bitcode, bitcodeSize);
+    if (!bitcodeMetadata.extract()) {
         ALOGE("Could not extract metadata from bitcode");
         return false;
     }
 
-    const char* core_lib = findCoreLib(ME, (const char*)bitcode, bitcodeSize);
+    const char* core_lib = findCoreLib(bitcodeMetadata, (const char*)bitcode, bitcodeSize);
 
     if (mCtx->getContext()->getContextType() == RS_CONTEXT_TYPE_DEBUG) {
         mCompilerDriver->setDebugContext(true);
         useRSDebugContext = true;
-        // Skip the cache lookup
-    } else if (!is_force_recompile()) {
-        // New cache infrastructure goes here
-
     }
 
-    if (exec == NULL) {
-        bool built = compileBitcode(cacheDir, resName, (const char *)bitcode,
-                                    bitcodeSize, core_lib, useRSDebugContext,
-                                    bccPluginName);
-        if (built) {
-            exec = bcc::RSCompilerDriver::loadScript(cacheDir, resName,
-                    (const char *)bitcode, bitcodeSize, mResolver);
+    android::String8 bcFileName(cacheDir);
+    bcFileName.append("/");
+    bcFileName.append(resName);
+    bcFileName.append(".bc");
+
+    std::vector<const char*> compileArguments;
+    setCompileArguments(&compileArguments, bcFileName, cacheDir, resName, core_lib,
+                        useRSDebugContext, bccPluginName);
+    // The last argument of compileArguments ia a NULL, so remove 1 from the size.
+    std::string compileCommandLine =
+                bcc::getCommandLine(compileArguments.size() - 1, compileArguments.data());
+
+    if (!is_force_recompile()) {
+        // Load the compiled script that's in the cache, if any.
+        mExecutable = bcc::RSCompilerDriver::loadScript(cacheDir, resName, (const char*)bitcode,
+                                                        bitcodeSize, compileCommandLine.c_str(),
+                                                        mResolver);
+    }
+
+    // If we can't, it's either not there or out of date.  We compile the bit code and try loading
+    // again.
+    if (mExecutable == NULL) {
+        if (!compileBitcode(bcFileName, (const char*)bitcode, bitcodeSize, compileArguments.data(),
+                            compileCommandLine)) {
+            ALOGE("bcc: FAILS to compile '%s'", resName);
+            mCtx->unlockMutex();
+            return false;
+        }
+        mExecutable = bcc::RSCompilerDriver::loadScript(cacheDir, resName, (const char*)bitcode,
+                                                        bitcodeSize, compileCommandLine.c_str(),
+                                                        mResolver);
+        if (mExecutable == NULL) {
+            ALOGE("bcc: FAILS to load freshly compiled executable for '%s'", resName);
+            mCtx->unlockMutex();
+            return false;
         }
     }
 
-    if (exec == NULL) {
-        ALOGE("bcc: FAILS to prepare executable for '%s'", resName);
-        mCtx->unlockMutex();
-        return false;
-    }
-
-    mExecutable = exec;
-
-    exec->setThreadable(mIsThreadable);
-    if (!exec->syncInfo()) {
+    mExecutable->setThreadable(mIsThreadable);
+    if (!mExecutable->syncInfo()) {
         ALOGW("bcc: FAILS to synchronize the RS info file to the disk");
     }
 
-    mRoot = reinterpret_cast<int (*)()>(exec->getSymbolAddress("root"));
+    mRoot = reinterpret_cast<int (*)()>(mExecutable->getSymbolAddress("root"));
     mRootExpand =
-        reinterpret_cast<int (*)()>(exec->getSymbolAddress("root.expand"));
-    mInit = reinterpret_cast<void (*)()>(exec->getSymbolAddress("init"));
+        reinterpret_cast<int (*)()>(mExecutable->getSymbolAddress("root.expand"));
+    mInit = reinterpret_cast<void (*)()>(mExecutable->getSymbolAddress("init"));
     mFreeChildren =
-        reinterpret_cast<void (*)()>(exec->getSymbolAddress(".rs.dtor"));
+        reinterpret_cast<void (*)()>(mExecutable->getSymbolAddress(".rs.dtor"));
 
 
-    if (ME.getExportVarCount()) {
-        mBoundAllocs = new Allocation *[ME.getExportVarCount()];
-        memset(mBoundAllocs, 0, sizeof(void *) * ME.getExportVarCount());
+    if (bitcodeMetadata.getExportVarCount()) {
+        mBoundAllocs = new Allocation *[bitcodeMetadata.getExportVarCount()];
+        memset(mBoundAllocs, 0, sizeof(void *) * bitcodeMetadata.getExportVarCount());
     }
 
-    for (size_t i = 0; i < ME.getExportForEachSignatureCount(); i++) {
-        char* name = new char[strlen(ME.getExportForEachNameList()[i]) + 1];
-        mExportedForEachFuncList.push_back(std::make_pair(name,
-                                                          ME.getExportForEachSignatureList()[i]));
+    for (size_t i = 0; i < bitcodeMetadata.getExportForEachSignatureCount(); i++) {
+        char* name = new char[strlen(bitcodeMetadata.getExportForEachNameList()[i]) + 1];
+        mExportedForEachFuncList.push_back(
+                    std::make_pair(name, bitcodeMetadata.getExportForEachSignatureList()[i]));
     }
 
 #else  // RS_COMPATIBILITY_LIB is defined
diff --git a/cpu_ref/rsCpuScript.h b/cpu_ref/rsCpuScript.h
index 7531a86..666379d 100644
--- a/cpu_ref/rsCpuScript.h
+++ b/cpu_ref/rsCpuScript.h
@@ -112,7 +112,8 @@
     const Script *mScript;
 
 #ifndef RS_COMPATIBILITY_LIB
-    const char* findCoreLib(const bcinfo::MetadataExtractor& ME, const char* bitcode,
+    // Returns the path to the core library we'll use.
+    const char* findCoreLib(const bcinfo::MetadataExtractor& bitCodeMetaData, const char* bitcode,
                             size_t bitcodeSize);
     int (*mRoot)();
     int (*mRootExpand)();
@@ -150,10 +151,8 @@
     Allocation **mBoundAllocs;
     void * mIntrinsicData;
     bool mIsThreadable;
-
 };
 
-
 Allocation * rsdScriptGetAllocationForPointer(
                         const Context *dc,
                         const Script *script,