Load scripts from cached files every time.

Bug: 7342767

Having an separate in-memory (vs. file-based) loader makes little sense as
we refactor libbcc (to separate it into its own process space). This change
is a first step in cleanly separating the compile and link steps.

Change-Id: Iad67527329171f18475ced0f0b2652a0aa060259
diff --git a/include/bcc/Renderscript/RSCompilerDriver.h b/include/bcc/Renderscript/RSCompilerDriver.h
index 7b54a13..9e74030 100644
--- a/include/bcc/Renderscript/RSCompilerDriver.h
+++ b/include/bcc/Renderscript/RSCompilerDriver.h
@@ -22,13 +22,13 @@
 #include "bcc/ExecutionEngine/SymbolResolverProxy.h"
 #include "bcc/Renderscript/RSInfo.h"
 #include "bcc/Renderscript/RSCompiler.h"
+#include "bcc/Renderscript/RSScript.h"
 
 namespace bcc {
 
 class BCCContext;
 class CompilerConfig;
 class RSExecutable;
-class RSScript;
 
 class RSCompilerDriver {
 private:
@@ -42,7 +42,7 @@
   // Are we compiling under an RS debug context with additional checks?
   bool mDebugContext;
 
-  RSExecutable *loadScriptCache(const char *pOutputPath,
+  RSExecutable *loadScriptCache(const char *pObjectPath,
                                 const RSInfo::DependencyTableTy &pDeps);
 
   // Setup the compiler config for the given script. Return true if mConfig has
diff --git a/include/bcc/Renderscript/RSInfo.h b/include/bcc/Renderscript/RSInfo.h
index f76813d..a0a775d 100644
--- a/include/bcc/Renderscript/RSInfo.h
+++ b/include/bcc/Renderscript/RSInfo.h
@@ -21,13 +21,16 @@
 
 #include <utility>
 
-#include "bcc/Renderscript/RSScript.h"
 #include "bcc/Support/Log.h"
 #include "bcc/Support/Sha1Util.h"
 
 #include <utils/String8.h>
 #include <utils/Vector.h>
 
+namespace llvm {
+class Module;
+}
+
 namespace bcc {
 
 // Forward declarations
@@ -35,6 +38,9 @@
 class InputFile;
 class OutputFile;
 class Source;
+class RSScript;
+
+typedef llvm::Module* (*RSLinkRuntimeCallback) (bcc::RSScript *, llvm::Module *, llvm::Module *);
 
 namespace rsinfo {
 
@@ -157,7 +163,7 @@
 
   // Return the path of the RS info file corresponded to the given output
   // executable file.
-  static android::String8 GetPath(const FileBase &pFile);
+  static android::String8 GetPath(const char *pFilename);
 
   static const char LibBCCPath[];
   static const char LibCompilerRTPath[];
diff --git a/include/bcc/Renderscript/RSScript.h b/include/bcc/Renderscript/RSScript.h
index b6c19ef..7f927c7 100644
--- a/include/bcc/Renderscript/RSScript.h
+++ b/include/bcc/Renderscript/RSScript.h
@@ -18,6 +18,7 @@
 #define BCC_RS_SCRIPT_H
 
 #include "bcc/Script.h"
+#include "bcc/Renderscript/RSInfo.h"
 #include "bcc/Support/Sha1Util.h"
 
 namespace llvm {
@@ -26,12 +27,9 @@
 
 namespace bcc {
 
-class RSInfo;
 class RSScript;
 class Source;
 
-typedef llvm::Module* (*RSLinkRuntimeCallback) (bcc::RSScript *, llvm::Module *, llvm::Module *);
-
 class RSScript : public Script {
 public:
   // This is one-one mapping with the llvm::CodeGenOpt::Level in
@@ -64,6 +62,10 @@
 
   RSScript(Source &pSource);
 
+  virtual ~RSScript() {
+    delete mInfo;
+  }
+
   // Set the associated RSInfo of the script.
   void setInfo(const RSInfo *pInfo) {
     mInfo = pInfo;
diff --git a/lib/Renderscript/RSCompilerDriver.cpp b/lib/Renderscript/RSCompilerDriver.cpp
index fd12760..32a2eaf 100644
--- a/lib/Renderscript/RSCompilerDriver.cpp
+++ b/lib/Renderscript/RSCompilerDriver.cpp
@@ -83,21 +83,18 @@
 }
 
 RSExecutable *
-RSCompilerDriver::loadScriptCache(const char *pOutputPath,
+RSCompilerDriver::loadScriptCache(const char *pObjectPath,
                                   const RSInfo::DependencyTableTy &pDeps) {
   //android::StopWatch load_time("bcc: RSCompilerDriver::loadScriptCache time");
   RSExecutable *result = NULL;
 
-  if (is_force_recompile())
-    return NULL;
-
   //===--------------------------------------------------------------------===//
-  // Acquire the read lock for reading output object file.
+  // Acquire the read lock for reading the Script object file.
   //===--------------------------------------------------------------------===//
-  FileMutex<FileBase::kReadLock> read_output_mutex(pOutputPath);
+  FileMutex<FileBase::kReadLock> read_output_mutex(pObjectPath);
 
   if (read_output_mutex.hasError() || !read_output_mutex.lock()) {
-    ALOGE("Unable to acquire the read lock for %s! (%s)", pOutputPath,
+    ALOGE("Unable to acquire the read lock for %s! (%s)", pObjectPath,
           read_output_mutex.getErrorMessage().c_str());
     return NULL;
   }
@@ -105,25 +102,25 @@
   //===--------------------------------------------------------------------===//
   // Read the output object file.
   //===--------------------------------------------------------------------===//
-  InputFile *output_file = new (std::nothrow) InputFile(pOutputPath);
+  InputFile *object_file = new (std::nothrow) InputFile(pObjectPath);
 
-  if ((output_file == NULL) || output_file->hasError()) {
-      //      ALOGE("Unable to open the %s for read! (%s)", pOutputPath,
-      //            output_file->getErrorMessage().c_str());
-    delete output_file;
+  if ((object_file == NULL) || object_file->hasError()) {
+      //      ALOGE("Unable to open the %s for read! (%s)", pObjectPath,
+      //            object_file->getErrorMessage().c_str());
+    delete object_file;
     return NULL;
   }
 
   //===--------------------------------------------------------------------===//
-  // Acquire the read lock on output_file for reading its RS info file.
+  // Acquire the read lock on object_file for reading its RS info file.
   //===--------------------------------------------------------------------===//
-  android::String8 info_path = RSInfo::GetPath(*output_file);
+  android::String8 info_path = RSInfo::GetPath(pObjectPath);
 
-  if (!output_file->lock()) {
+  if (!object_file->lock()) {
     ALOGE("Unable to acquire the read lock on %s for reading %s! (%s)",
-          pOutputPath, info_path.string(),
-          output_file->getErrorMessage().c_str());
-    delete output_file;
+          pObjectPath, info_path.string(),
+          object_file->getErrorMessage().c_str());
+    delete object_file;
     return NULL;
   }
 
@@ -133,20 +130,20 @@
   InputFile info_file(info_path.string());
   RSInfo *info = RSInfo::ReadFromFile(info_file, pDeps);
 
-  // Release the lock on output_file.
-  output_file->unlock();
+  // Release the lock on object_file.
+  object_file->unlock();
 
   if (info == NULL) {
-    delete output_file;
+    delete object_file;
     return NULL;
   }
 
   //===--------------------------------------------------------------------===//
   // Create the RSExecutable.
   //===--------------------------------------------------------------------===//
-  result = RSExecutable::Create(*info, *output_file, mResolver);
+  result = RSExecutable::Create(*info, *object_file, mResolver);
   if (result == NULL) {
-    delete output_file;
+    delete object_file;
     delete info;
     return NULL;
   }
@@ -199,7 +196,6 @@
                                 const RSInfo::DependencyTableTy &pDeps,
                                 bool pSkipLoad) {
   //android::StopWatch compile_time("bcc: RSCompilerDriver::compileScript time");
-  RSExecutable *result = NULL;
   RSInfo *info = NULL;
 
   //===--------------------------------------------------------------------===//
@@ -227,70 +223,52 @@
     return NULL;
   }
 
-  //===--------------------------------------------------------------------===//
-  // Acquire the write lock for writing output object file.
-  //===--------------------------------------------------------------------===//
-  FileMutex<FileBase::kWriteLock> write_output_mutex(pOutputPath);
+  {
+    // Acquire the write lock for writing output object file.
+    FileMutex<FileBase::kWriteLock> write_output_mutex(pOutputPath);
 
-  if (write_output_mutex.hasError() || !write_output_mutex.lock()) {
-    ALOGE("Unable to acquire the lock for writing %s! (%s)",
-          pOutputPath, write_output_mutex.getErrorMessage().c_str());
-    return NULL;
-  }
-
-  //===--------------------------------------------------------------------===//
-  // Open the output file for write.
-  //===--------------------------------------------------------------------===//
-  unsigned flags = FileBase::kTruncate;
-  if (mDebugContext) {
-    // Delete the cache file when we finish up under a debug context.
-    flags |= FileBase::kDeleteOnClose;
-  }
-  OutputFile *output_file = new (std::nothrow) OutputFile(pOutputPath, flags);
-
-  if ((output_file == NULL) || output_file->hasError()) {
-      ALOGE("Unable to open %s for write! (%s)", pOutputPath,
-            output_file->getErrorMessage().c_str());
-    delete info;
-    delete output_file;
-    return NULL;
-  }
-
-  //===--------------------------------------------------------------------===//
-  // Setup the config to the compiler.
-  //===--------------------------------------------------------------------===//
-  bool compiler_need_reconfigure = setupConfig(pScript);
-
-  if (mConfig == NULL) {
-    ALOGE("Failed to setup config for RS compiler to compile %s!", pOutputPath);
-    delete info;
-    delete output_file;
-    return NULL;
-  }
-
-  // Compiler need to re-config if it's haven't run the config() yet or the
-  // configuration it referenced is changed.
-  if (compiler_need_reconfigure) {
-    Compiler::ErrorCode err = mCompiler.config(*mConfig);
-    if (err != Compiler::kSuccess) {
-      ALOGE("Failed to config the RS compiler for %s! (%s)",pOutputPath,
-            Compiler::GetErrorString(err));
-      delete info;
-      delete output_file;
+    if (write_output_mutex.hasError() || !write_output_mutex.lock()) {
+      ALOGE("Unable to acquire the lock for writing %s! (%s)",
+            pOutputPath, write_output_mutex.getErrorMessage().c_str());
       return NULL;
     }
-  }
 
-  //===--------------------------------------------------------------------===//
-  // Run the compiler.
-  //===--------------------------------------------------------------------===//
-  Compiler::ErrorCode compile_result = mCompiler.compile(pScript, *output_file);
-  if (compile_result != Compiler::kSuccess) {
-    ALOGE("Unable to compile the source to file %s! (%s)", pOutputPath,
-          Compiler::GetErrorString(compile_result));
-    delete info;
-    delete output_file;
-    return NULL;
+    // Open the output file for write.
+    OutputFile output_file(pOutputPath, FileBase::kTruncate);
+
+    if (output_file.hasError()) {
+        ALOGE("Unable to open %s for write! (%s)", pOutputPath,
+              output_file.getErrorMessage().c_str());
+      return NULL;
+    }
+
+    // Setup the config to the compiler.
+    bool compiler_need_reconfigure = setupConfig(pScript);
+
+    if (mConfig == NULL) {
+      ALOGE("Failed to setup config for RS compiler to compile %s!",
+            pOutputPath);
+      return NULL;
+    }
+
+    if (compiler_need_reconfigure) {
+      Compiler::ErrorCode err = mCompiler.config(*mConfig);
+      if (err != Compiler::kSuccess) {
+        ALOGE("Failed to config the RS compiler for %s! (%s)",pOutputPath,
+              Compiler::GetErrorString(err));
+        return NULL;
+      }
+    }
+
+    // Run the compiler.
+    Compiler::ErrorCode compile_result =
+        mCompiler.compile(pScript, output_file);
+
+    if (compile_result != Compiler::kSuccess) {
+      ALOGE("Unable to compile the source to file %s! (%s)", pOutputPath,
+            Compiler::GetErrorString(compile_result));
+      return NULL;
+    }
   }
 
   // No need to produce an RSExecutable in this case.
@@ -299,41 +277,31 @@
     return NULL;
   }
 
-  //===--------------------------------------------------------------------===//
-  // Create the RSExecutable.
-  //===--------------------------------------------------------------------===//
-  result = RSExecutable::Create(*info, *output_file, mResolver);
-  if (result == NULL) {
-    delete info;
-    delete output_file;
-    return NULL;
+  {
+    android::String8 info_path = RSInfo::GetPath(pOutputPath);
+    OutputFile info_file(info_path.string(), FileBase::kTruncate);
+
+    if (info_file.hasError()) {
+      ALOGE("Failed to open the info file %s for write! (%s)",
+            info_path.string(), info_file.getErrorMessage().c_str());
+      return NULL;
+    }
+
+    FileMutex<FileBase::kWriteLock> write_info_mutex(info_path.string());
+    if (write_info_mutex.hasError() || !write_info_mutex.lock()) {
+      ALOGE("Unable to acquire the lock for writing %s! (%s)",
+            info_path.string(), write_info_mutex.getErrorMessage().c_str());
+      return NULL;
+    }
+
+    // Perform the write.
+    if (!info->write(info_file)) {
+      ALOGE("Failed to sync the RS info file %s!", info_path.string());
+      return NULL;
+    }
   }
 
-  //===--------------------------------------------------------------------===//
-  // Dump the disassembly for debug when possible.
-  //===--------------------------------------------------------------------===//
-#if USE_DISASSEMBLER
-  OutputFile *disassembly_output =
-      new (std::nothrow) OutputFile(DEBUG_DISASSEMBLER_FILE,
-                                    FileBase::kAppend);
-
-  if (disassembly_output != NULL) {
-    result->dumpDisassembly(*disassembly_output);
-    delete disassembly_output;
-  }
-#endif
-
-  //===--------------------------------------------------------------------===//
-  // Write out the RS info file.
-  //===--------------------------------------------------------------------===//
-  // Note that write failure only results in a warning since the source is
-  // successfully compiled and loaded.
-  if (!result->syncInfo(/* pForce */true)) {
-    ALOGW("%s was successfully compiled and loaded but its RS info file failed "
-          "to write out!", pOutputPath);
-  }
-
-  return result;
+  return loadScriptCache(pOutputPath, pDeps);
 }
 
 RSExecutable *RSCompilerDriver::build(BCCContext &pContext,
@@ -387,8 +355,8 @@
   //===--------------------------------------------------------------------===//
   RSExecutable *result = NULL;
 
-  // Skip loading from the cache if we are using a debug context.
-  if (!mDebugContext) {
+  // Skip loading from the cache if we are using a debug context (or setprop).
+  if (!mDebugContext && !is_force_recompile()) {
     result = loadScriptCache(output_path.c_str(), dep_info);
 
     if (result != NULL) {
diff --git a/lib/Renderscript/RSExecutable.cpp b/lib/Renderscript/RSExecutable.cpp
index be39f3c..ed06f30 100644
--- a/lib/Renderscript/RSExecutable.cpp
+++ b/lib/Renderscript/RSExecutable.cpp
@@ -129,7 +129,7 @@
     return true;
   }
 
-  android::String8 info_path = RSInfo::GetPath(*mObjFile);
+  android::String8 info_path = RSInfo::GetPath(mObjFile->getName().c_str());
   OutputFile info_file(info_path.string(), FileBase::kTruncate);
 
   if (info_file.hasError()) {
diff --git a/lib/Renderscript/RSInfo.cpp b/lib/Renderscript/RSInfo.cpp
index b289079..7442012 100644
--- a/lib/Renderscript/RSInfo.cpp
+++ b/lib/Renderscript/RSInfo.cpp
@@ -86,8 +86,8 @@
 #endif  // TARGET_BUILD
 }
 
-android::String8 RSInfo::GetPath(const FileBase &pFile) {
-  android::String8 result(pFile.getName().c_str());
+android::String8 RSInfo::GetPath(const char *pFilename) {
+  android::String8 result(pFilename);
   result.append(".info");
   return result;
 }