am 97c92c2d: Revert "Introduce new Script class."

* commit '97c92c2d0604ea9cc4cd878f0f1901efc79c8835':
  Revert "Introduce new Script class."
diff --git a/lib/ExecutionEngine/Android.mk b/lib/ExecutionEngine/Android.mk
index e26be60..855d055 100644
--- a/lib/ExecutionEngine/Android.mk
+++ b/lib/ExecutionEngine/Android.mk
@@ -31,7 +31,6 @@
   GDBJITRegistrar.cpp \
   MCCacheWriter.cpp \
   MCCacheReader.cpp \
-  RSScript.cpp \
   Runtime.c \
   RuntimeStub.c \
   Script.cpp \
diff --git a/lib/ExecutionEngine/MCCacheWriter.cpp b/lib/ExecutionEngine/MCCacheWriter.cpp
index b113ad9..b0bf117 100644
--- a/lib/ExecutionEngine/MCCacheWriter.cpp
+++ b/lib/ExecutionEngine/MCCacheWriter.cpp
@@ -18,7 +18,7 @@
 
 #include "DebugHelper.h"
 #include "FileHandle.h"
-#include "RSScript.h"
+#include "Script.h"
 
 #include <map>
 #include <string>
@@ -48,7 +48,7 @@
 }
 
 bool MCCacheWriter::writeCacheFile(FileHandle *objFile, FileHandle *infoFile,
-                                   RSScript *S, uint32_t libRS_threadable) {
+                                 Script *S, uint32_t libRS_threadable) {
   if (!objFile || objFile->getFD() < 0 || !infoFile || infoFile->getFD() < 0) {
     return false;
   }
diff --git a/lib/ExecutionEngine/MCCacheWriter.h b/lib/ExecutionEngine/MCCacheWriter.h
index 7fa5cf5..b2bcb12 100644
--- a/lib/ExecutionEngine/MCCacheWriter.h
+++ b/lib/ExecutionEngine/MCCacheWriter.h
@@ -27,11 +27,11 @@
 #include <vector>
 
 namespace bcc {
-  class RSScript;
+  class Script;
 
   class MCCacheWriter {
   private:
-    RSScript *mpOwner;
+    Script *mpOwner;
 
     FileHandle *mObjFile, *mInfoFile;
 
@@ -64,7 +64,7 @@
     ~MCCacheWriter();
 
     bool writeCacheFile(FileHandle *objFile, FileHandle *infoFile,
-                        RSScript *S, uint32_t libRS_threadable);
+                        Script *S, uint32_t libRS_threadable);
 
     void addDependency(MCO_ResourceType resType,
                        std::string const &resName,
diff --git a/lib/ExecutionEngine/RSScript.cpp b/lib/ExecutionEngine/RSScript.cpp
deleted file mode 100644
index af37ab6..0000000
--- a/lib/ExecutionEngine/RSScript.cpp
+++ /dev/null
@@ -1,730 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#include "Script.h"
-
-#include <errno.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#include <new>
-#include <cstring>
-
-#include <llvm/ADT/STLExtras.h>
-
-#include <cutils/properties.h>
-
-#include "Config.h"
-
-#include "MCCacheReader.h"
-#include "MCCacheWriter.h"
-#include "CompilerOption.h"
-
-#include "DebugHelper.h"
-#include "FileHandle.h"
-#include "GDBJITRegistrar.h"
-#include "ScriptCompiled.h"
-#include "ScriptCached.h"
-#include "Sha1Helper.h"
-#include "Source.h"
-
-namespace {
-
-bool getBooleanProp(const char *str) {
-  char buf[PROPERTY_VALUE_MAX];
-  property_get(str, buf, "0");
-  return strcmp(buf, "0") != 0;
-}
-
-} // namespace anonymous
-
-namespace bcc {
-
-RSScript::SourceDependency::SourceDependency(MCO_ResourceType pSourceType,
-                                             const std::string &pSourceName,
-                                             const uint8_t *pSHA1)
-  : mSourceType(pSourceType), mSourceName(pSourceName) {
-  ::memcpy(mSHA1, pSHA1, sizeof(mSHA1));
-  return;
-}
-
-RSScript::RSScript(Source &pSource)
-  : Script(pSource),
-    mpExtSymbolLookupFn(NULL),
-    mpExtSymbolLookupFnContext(NULL) {
-  resetState();
-  return;
-}
-
-RSScript::~RSScript() {
-  switch (mStatus) {
-  case ScriptStatus::Compiled:
-    delete mCompiled;
-    break;
-
-  case ScriptStatus::Cached:
-    delete mCached;
-    break;
-
-  default:
-    break;
-  }
-  llvm::DeleteContainerPointers(mSourceDependencies);
-}
-
-void RSScript::resetState() {
-  mErrorCode = BCC_NO_ERROR;
-  mStatus = ScriptStatus::Unknown;
-  mObjectType = ScriptObject::Unknown;
-  mIsContextSlotNotAvail = false;
-  // FIXME: mpExtSymbolLookupFn and mpExtSymbolLookupFnContext should be assign
-  //        to NULL during state resetting.
-  //mpExtSymbolLookupFn = NULL;
-  //mpExtSymbolLookupFnContext = NULL;
-  llvm::DeleteContainerPointers(mSourceDependencies);
-  return;
-}
-
-
-bool RSScript::doReset() {
-  resetState();
-  return true;
-}
-
-bool RSScript::addSourceDependency(MCO_ResourceType pSourceType,
-                                   const std::string &pSourceName,
-                                   const uint8_t *pSHA1) {
-  SourceDependency *source_dep =
-      new (std::nothrow) SourceDependency(pSourceType, pSourceName, pSHA1);
-  if (source_dep == NULL) {
-    ALOGE("Out of memory when record dependency information of `%s'!",
-          pSourceName.c_str());
-    return false;
-  }
-
-  mSourceDependencies.push_back(source_dep);
-  return true;
-}
-
-int RSScript::prepareRelocatable(char const *objPath,
-                               llvm::Reloc::Model RelocModel,
-                               unsigned long flags) {
-  CompilerOption option;
-  option.RelocModelOpt = RelocModel;
-  option.LoadAfterCompile = false;
-
-  int status = internalCompile(option);
-  if (status != 0) {
-    ALOGE("LLVM error message: %s\n", getCompilerErrorMessage());
-    return status;
-  }
-
-  FileHandle objFile;
-  if (objFile.open(objPath, OpenMode::Write) < 1) {
-    ALOGE("Failed to open %s for write.\n", objPath);
-    return 1;
-  }
-
-  if (static_cast<size_t>(objFile.write(getELF(),
-                                        getELFSize())) != getELFSize()) {
-      objFile.close();
-      ::unlink(objPath);
-      ALOGE("Unable to write ELF to file %s.\n", objPath);
-      return false;
-  }
-
-  mObjectType = ScriptObject::Relocatable;
-
-  return 0;
-}
-
-
-int RSScript::prepareSharedObject(char const *objPath,
-                                char const *dsoPath,
-                                unsigned long flags) {
-  // TODO: Support cached shared object.
-  return 1;
-}
-
-
-int RSScript::prepareExecutable(char const *cacheDir,
-                              char const *cacheName,
-                              unsigned long flags) {
-  if (mStatus != ScriptStatus::Unknown) {
-    mErrorCode = BCC_INVALID_OPERATION;
-    ALOGE("Invalid operation: %s\n", __func__);
-    return 1;
-  }
-
-  int status = internalLoadCache(cacheDir, cacheName, /* checkOnly */ false);
-
-  if (status != 0) {
-    CompilerOption option;
-    status = internalCompile(option);
-
-    if (status != 0) {
-      ALOGE("LLVM error message: %s\n", getCompilerErrorMessage());
-      return status;
-    }
-
-    status = writeCache();
-    if (status != 0) {
-      ALOGE("Failed to write the cache for %s\n", cacheName);
-      return status;
-    }
-  }
-
-  // FIXME: Registration can be conditional on the presence of debug metadata
-  registerObjectWithGDB(getELF(), getELFSize()); // thread-safe registration
-
-  mObjectType = ScriptObject::Executable;
-
-  return status;
-}
-
-int RSScript::internalLoadCache(char const *cacheDir, char const *cacheName,
-                              bool checkOnly) {
-  if ((cacheDir == NULL) || (cacheName == NULL)) {
-    return 1;
-  }
-
-  // Set cache file Name
-  mCacheName = cacheName;
-
-  // Santize mCacheDir. Ensure that mCacheDir ends with '/'.
-  mCacheDir = cacheDir;
-  if (!mCacheDir.empty() && *mCacheDir.rbegin() != '/') {
-    mCacheDir.push_back('/');
-  }
-
-  if (!isCacheable()) {
-    return 1;
-  }
-
-  std::string objPath = getCachedObjectPath();
-  std::string infoPath = getCacheInfoPath();
-
-  FileHandle objFile;
-  if (objFile.open(objPath.c_str(), OpenMode::Read) < 0) {
-    // Unable to open the executable file in read mode.
-    return 1;
-  }
-
-  FileHandle infoFile;
-  if (infoFile.open(infoPath.c_str(), OpenMode::Read) < 0) {
-    // Unable to open the metadata information file in read mode.
-    return 1;
-  }
-
-  MCCacheReader reader;
-
-  // Register symbol lookup function
-  if (mpExtSymbolLookupFn) {
-    reader.registerSymbolCallback(mpExtSymbolLookupFn,
-                                      mpExtSymbolLookupFnContext);
-  }
-
-  // Dependencies
-  reader.addDependency(BCC_FILE_RESOURCE, pathLibBCC_SHA1, sha1LibBCC_SHA1);
-  reader.addDependency(BCC_FILE_RESOURCE, pathLibRS, sha1LibRS);
-
-  for (unsigned i = 0; i < mSourceDependencies.size(); i++) {
-    const SourceDependency *source_dep = mSourceDependencies[i];
-    reader.addDependency(source_dep->getSourceType(),
-                         source_dep->getSourceName(),
-                         source_dep->getSHA1Checksum());
-  }
-
-  if (checkOnly)
-    return !reader.checkCacheFile(&objFile, &infoFile, this);
-
-  // Read cache file
-  ScriptCached *cached = reader.readCacheFile(&objFile, &infoFile, this);
-
-  if (!cached) {
-    mIsContextSlotNotAvail = reader.isContextSlotNotAvail();
-    return 1;
-  }
-
-  mCached = cached;
-  mStatus = ScriptStatus::Cached;
-
-  // Dirty hack for libRS.
-  // TODO(all):  This dirty hack should be removed in the future.
-  if (!cached->isLibRSThreadable() && mpExtSymbolLookupFn) {
-    mpExtSymbolLookupFn(mpExtSymbolLookupFnContext, "__clearThreadable");
-  }
-
-  return 0;
-}
-
-int RSScript::internalCompile(const CompilerOption &option) {
-  // Create the ScriptCompiled object
-  mCompiled = new (std::nothrow) ScriptCompiled(this);
-
-  if (!mCompiled) {
-    mErrorCode = BCC_OUT_OF_MEMORY;
-    ALOGE("Out of memory: %s %d\n", __FILE__, __LINE__);
-    return 1;
-  }
-
-  mStatus = ScriptStatus::Compiled;
-
-  // Register symbol lookup function
-  if (mpExtSymbolLookupFn) {
-    mCompiled->registerSymbolCallback(mpExtSymbolLookupFn,
-                                      mpExtSymbolLookupFnContext);
-  }
-
-  // Set the main source module
-  if (mCompiled->readModule(getSource().getModule()) != 0) {
-    ALOGE("Unable to read source module\n");
-    return 1;
-  }
-
-  // Compile and JIT the code
-  if (mCompiled->compile(option) != 0) {
-    ALOGE("Unable to compile.\n");
-    return 1;
-  }
-
-  return 0;
-}
-
-int RSScript::writeCache() {
-  // Not compiled script or encountered error during the compilation.
-  if ((mStatus != ScriptStatus::Compiled) ||
-      (getCompilerErrorMessage() == NULL))
-    return 1;
-
-  // Note: If we re-compile the script because the cached context slot not
-  // available, then we don't have to write the cache.
-
-  // Note: If the address of the context is not in the context slot, then
-  // we don't have to cache it.
-
-  if (isCacheable()) {
-
-    std::string objPath = getCachedObjectPath();
-    std::string infoPath = getCacheInfoPath();
-
-    // Remove the file if it already exists before writing the new file.
-    // The old file may still be mapped elsewhere in memory and we do not want
-    // to modify its contents.  (The same script may be running concurrently in
-    // the same process or a different process!)
-    ::unlink(objPath.c_str());
-    ::unlink(infoPath.c_str());
-
-    FileHandle objFile;
-    FileHandle infoFile;
-
-    if (objFile.open(objPath.c_str(), OpenMode::Write) >= 0 &&
-        infoFile.open(infoPath.c_str(), OpenMode::Write) >= 0) {
-
-      MCCacheWriter writer;
-
-#ifdef TARGET_BUILD
-      // Dependencies
-      writer.addDependency(BCC_FILE_RESOURCE, pathLibBCC_SHA1, sha1LibBCC_SHA1);
-      writer.addDependency(BCC_FILE_RESOURCE, pathLibRS, sha1LibRS);
-#endif
-
-      for (unsigned i = 0; i < mSourceDependencies.size(); i++) {
-        const SourceDependency *source_dep = mSourceDependencies[i];
-        writer.addDependency(source_dep->getSourceType(),
-                             source_dep->getSourceName(),
-                             source_dep->getSHA1Checksum());
-      }
-
-
-      // libRS is threadable dirty hack
-      // TODO: This should be removed in the future
-      uint32_t libRS_threadable = 0;
-      if (mpExtSymbolLookupFn) {
-        libRS_threadable =
-          (uint32_t)mpExtSymbolLookupFn(mpExtSymbolLookupFnContext,
-                                        "__isThreadable");
-      }
-
-      if (!writer.writeCacheFile(&objFile, &infoFile, this, libRS_threadable)) {
-        objFile.truncate();
-        objFile.close();
-
-        if (unlink(objPath.c_str()) != 0) {
-          ALOGE("Unable to remove the invalid cache file: %s. (reason: %s)\n",
-               objPath.c_str(), strerror(errno));
-        }
-
-        infoFile.truncate();
-        infoFile.close();
-
-        if (unlink(infoPath.c_str()) != 0) {
-          ALOGE("Unable to remove the invalid cache file: %s. (reason: %s)\n",
-               infoPath.c_str(), strerror(errno));
-        }
-      }
-    }
-  }
-
-  return 0;
-}
-
-
-char const *RSScript::getCompilerErrorMessage() {
-  if (mStatus != ScriptStatus::Compiled) {
-    mErrorCode = BCC_INVALID_OPERATION;
-    return NULL;
-  }
-
-  return mCompiled->getCompilerErrorMessage();
-}
-
-
-void *RSScript::lookup(const char *name) {
-  switch (mStatus) {
-    case ScriptStatus::Compiled: {
-      return mCompiled->lookup(name);
-    }
-
-    case ScriptStatus::Cached: {
-      return mCached->lookup(name);
-    }
-
-    default: {
-      mErrorCode = BCC_INVALID_OPERATION;
-      return NULL;
-    }
-  }
-}
-
-
-size_t RSScript::getExportVarCount() const {
-  switch (mStatus) {
-    case ScriptStatus::Compiled: {
-      return mCompiled->getExportVarCount();
-    }
-
-    case ScriptStatus::Cached: {
-      return mCached->getExportVarCount();
-    }
-
-    default: {
-      return 0;
-    }
-  }
-}
-
-
-size_t RSScript::getExportFuncCount() const {
-  switch (mStatus) {
-    case ScriptStatus::Compiled: {
-      return mCompiled->getExportFuncCount();
-    }
-
-    case ScriptStatus::Cached: {
-      return mCached->getExportFuncCount();
-    }
-
-    default: {
-      return 0;
-    }
-  }
-}
-
-
-size_t RSScript::getExportForEachCount() const {
-  switch (mStatus) {
-    case ScriptStatus::Compiled: {
-      return mCompiled->getExportForEachCount();
-    }
-
-    case ScriptStatus::Cached: {
-      return mCached->getExportForEachCount();
-    }
-
-    default: {
-      return 0;
-    }
-  }
-}
-
-
-size_t RSScript::getPragmaCount() const {
-  switch (mStatus) {
-    case ScriptStatus::Compiled: {
-      return mCompiled->getPragmaCount();
-    }
-
-    case ScriptStatus::Cached: {
-      return mCached->getPragmaCount();
-    }
-
-    default: {
-      return 0;
-    }
-  }
-}
-
-
-size_t RSScript::getFuncCount() const {
-  switch (mStatus) {
-    case ScriptStatus::Compiled: {
-      return mCompiled->getFuncCount();
-    }
-
-    case ScriptStatus::Cached: {
-      return mCached->getFuncCount();
-    }
-
-    default: {
-      return 0;
-    }
-  }
-}
-
-
-size_t RSScript::getObjectSlotCount() const {
-  switch (mStatus) {
-    case ScriptStatus::Compiled: {
-      return mCompiled->getObjectSlotCount();
-    }
-
-    case ScriptStatus::Cached: {
-      return mCached->getObjectSlotCount();
-    }
-
-    default: {
-      return 0;
-    }
-  }
-}
-
-
-void RSScript::getExportVarList(size_t varListSize, void **varList) {
-  switch (mStatus) {
-#define DELEGATE(STATUS) \
-    case ScriptStatus::STATUS:                           \
-      m##STATUS->getExportVarList(varListSize, varList); \
-      break;
-
-    DELEGATE(Cached);
-
-    DELEGATE(Compiled);
-#undef DELEGATE
-
-    default: {
-      mErrorCode = BCC_INVALID_OPERATION;
-    }
-  }
-}
-
-void RSScript::getExportVarNameList(std::vector<std::string> &varList) {
-  switch (mStatus) {
-    case ScriptStatus::Compiled: {
-      return mCompiled->getExportVarNameList(varList);
-    }
-
-    default: {
-      mErrorCode = BCC_INVALID_OPERATION;
-    }
-  }
-}
-
-
-void RSScript::getExportFuncList(size_t funcListSize, void **funcList) {
-  switch (mStatus) {
-#define DELEGATE(STATUS) \
-    case ScriptStatus::STATUS:                              \
-      m##STATUS->getExportFuncList(funcListSize, funcList); \
-      break;
-
-    DELEGATE(Cached);
-
-    DELEGATE(Compiled);
-#undef DELEGATE
-
-    default: {
-      mErrorCode = BCC_INVALID_OPERATION;
-    }
-  }
-}
-
-void RSScript::getExportFuncNameList(std::vector<std::string> &funcList) {
-  switch (mStatus) {
-    case ScriptStatus::Compiled: {
-      return mCompiled->getExportFuncNameList(funcList);
-    }
-
-    default: {
-      mErrorCode = BCC_INVALID_OPERATION;
-    }
-  }
-}
-
-void RSScript::getExportForEachList(size_t funcListSize, void **funcList) {
-  switch (mStatus) {
-#define DELEGATE(STATUS) \
-    case ScriptStatus::STATUS:                                 \
-      m##STATUS->getExportForEachList(funcListSize, funcList); \
-      break;
-
-    DELEGATE(Cached);
-
-    DELEGATE(Compiled);
-#undef DELEGATE
-
-    default: {
-      mErrorCode = BCC_INVALID_OPERATION;
-    }
-  }
-}
-
-void RSScript::getExportForEachNameList(std::vector<std::string> &forEachList) {
-  switch (mStatus) {
-    case ScriptStatus::Compiled: {
-      return mCompiled->getExportForEachNameList(forEachList);
-    }
-
-    default: {
-      mErrorCode = BCC_INVALID_OPERATION;
-    }
-  }
-}
-
-void RSScript::getPragmaList(size_t pragmaListSize,
-                           char const **keyList,
-                           char const **valueList) {
-  switch (mStatus) {
-#define DELEGATE(STATUS) \
-    case ScriptStatus::STATUS:                                      \
-      m##STATUS->getPragmaList(pragmaListSize, keyList, valueList); \
-      break;
-
-    DELEGATE(Cached);
-
-    DELEGATE(Compiled);
-#undef DELEGATE
-
-    default: {
-      mErrorCode = BCC_INVALID_OPERATION;
-    }
-  }
-}
-
-
-void RSScript::getFuncInfoList(size_t funcInfoListSize,
-                             FuncInfo *funcInfoList) {
-  switch (mStatus) {
-#define DELEGATE(STATUS) \
-    case ScriptStatus::STATUS:                                    \
-      m##STATUS->getFuncInfoList(funcInfoListSize, funcInfoList); \
-      break;
-
-    DELEGATE(Cached);
-
-    DELEGATE(Compiled);
-#undef DELEGATE
-
-    default: {
-      mErrorCode = BCC_INVALID_OPERATION;
-    }
-  }
-}
-
-
-void RSScript::getObjectSlotList(size_t objectSlotListSize,
-                               uint32_t *objectSlotList) {
-  switch (mStatus) {
-#define DELEGATE(STATUS)     \
-    case ScriptStatus::STATUS:                                          \
-      m##STATUS->getObjectSlotList(objectSlotListSize, objectSlotList); \
-      break;
-
-    DELEGATE(Cached);
-
-    DELEGATE(Compiled);
-#undef DELEGATE
-
-    default: {
-      mErrorCode = BCC_INVALID_OPERATION;
-    }
-  }
-}
-
-
-int RSScript::registerSymbolCallback(BCCSymbolLookupFn pFn, void *pContext) {
-  mpExtSymbolLookupFn = pFn;
-  mpExtSymbolLookupFnContext = pContext;
-
-  if (mStatus != ScriptStatus::Unknown) {
-    mErrorCode = BCC_INVALID_OPERATION;
-    ALOGE("Invalid operation: %s\n", __func__);
-    return 1;
-  }
-  return 0;
-}
-
-bool RSScript::isCacheable() const {
-  if (getBooleanProp("debug.bcc.nocache")) {
-    // Android system environment property: Disables the cache mechanism by
-    // setting "debug.bcc.nocache".  So we will not load the cache file any
-    // way.
-    return false;
-  }
-
-  if (mCacheDir.empty() || mCacheName.empty()) {
-    // The application developer has not specified the cachePath, so
-    // we don't know where to open the cache file.
-    return false;
-  }
-
-  return true;
-}
-
-size_t RSScript::getELFSize() const {
-  switch (mStatus) {
-    case ScriptStatus::Compiled: {
-      return mCompiled->getELFSize();
-    }
-
-    case ScriptStatus::Cached: {
-      return mCached->getELFSize();
-    }
-
-    default: {
-      return 0;
-    }
-  }
-}
-
-const char *RSScript::getELF() const {
-  switch (mStatus) {
-    case ScriptStatus::Compiled: {
-      return mCompiled->getELF();
-    }
-
-    case ScriptStatus::Cached: {
-      return mCached->getELF();
-    }
-
-    default: {
-      return NULL;
-    }
-  }
-}
-
-} // namespace bcc
diff --git a/lib/ExecutionEngine/RSScript.h b/lib/ExecutionEngine/RSScript.h
deleted file mode 100644
index 6e4cd9f..0000000
--- a/lib/ExecutionEngine/RSScript.h
+++ /dev/null
@@ -1,249 +0,0 @@
-/*
- * Copyright 2012, The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-#ifndef BCC_EXECUTION_ENGINE_RS_SCRIPT_H
-#define BCC_EXECUTION_ENGINE_RS_SCRIPT_H
-
-#include <vector>
-#include <string>
-
-#include <stdint.h>
-#include <stddef.h>
-
-#include <llvm/ADT/SmallVector.h>
-
-#include <bcc/bcc.h>
-#include <bcc/bcc_mccache.h>
-#include "bcc_internal.h"
-
-#include "Compiler.h"
-#include "Script.h"
-
-namespace llvm {
-  class Module;
-  class GDBJITRegistrar;
-}
-
-namespace bcc {
-  class ScriptCompiled;
-  class ScriptCached;
-  class Source;
-  struct CompilerOption;
-
-  namespace ScriptStatus {
-    enum StatusType {
-      Unknown,
-      Compiled,
-      Cached
-    };
-  }
-
-  namespace ScriptObject {
-    enum ObjectType {
-      Unknown,
-      Relocatable,
-      SharedObject,
-      Executable,
-    };
-  }
-
-  class RSScript : public Script {
-  public:
-    class SourceDependency {
-    private:
-      MCO_ResourceType mSourceType;
-      std::string mSourceName;
-      uint8_t mSHA1[20];
-
-    public:
-      SourceDependency(MCO_ResourceType pSourceType,
-                       const std::string &pSourceName,
-                       const uint8_t *pSHA1);
-
-      inline MCO_ResourceType getSourceType() const
-      { return mSourceType; }
-
-      inline const std::string &getSourceName() const
-      { return mSourceName; }
-
-      inline const uint8_t *getSHA1Checksum() const
-      { return mSHA1; }
-    };
-    typedef llvm::SmallVectorImpl<SourceDependency *> SourceDependencyListTy;
-
-  private:
-    int mErrorCode;
-
-    ScriptStatus::StatusType mStatus;
-    // The type of the object behind this script after compilation. For
-    // example, after returning from a successful call to prepareRelocatable(),
-    // the value of mObjectType will be ScriptObject::Relocatable.
-    ScriptObject::ObjectType mObjectType;
-
-    union {
-      ScriptCompiled *mCompiled;
-      ScriptCached *mCached;
-    };
-
-    std::string mCacheDir;
-    std::string mCacheName;
-
-    inline std::string getCachedObjectPath() const {
-      return std::string(mCacheDir + mCacheName + ".o");
-    }
-
-    inline std::string getCacheInfoPath() const {
-      return getCachedObjectPath().append(".info");
-    }
-
-    bool mIsContextSlotNotAvail;
-
-    llvm::SmallVector<SourceDependency *, 4> mSourceDependencies;
-
-    // External Function List
-    std::vector<char const *> mUserDefinedExternalSymbols;
-
-    // Register Symbol Lookup Function
-    BCCSymbolLookupFn mpExtSymbolLookupFn;
-    void *mpExtSymbolLookupFnContext;
-
-    // This will be invoked when the containing source has been reset.
-    virtual bool doReset();
-
-    // Reset the state of this script object
-    void resetState();
-
-  public:
-    RSScript(Source &pSource);
-
-    ~RSScript();
-
-    // Add dependency information for this script given the source named
-    // pSourceName. pSHA1 is the SHA-1 checksum of the given source. Return
-    // false on error.
-    bool addSourceDependency(MCO_ResourceType pSourceType,
-                             const std::string &pSourceName,
-                             const uint8_t *pSHA1);
-
-    const SourceDependencyListTy &getSourceDependencies() const
-    { return mSourceDependencies; }
-
-    void markExternalSymbol(char const *name) {
-      mUserDefinedExternalSymbols.push_back(name);
-    }
-
-    std::vector<char const *> const &getUserDefinedExternalSymbols() const {
-      return mUserDefinedExternalSymbols;
-    }
-
-    int prepareExecutable(char const *cacheDir,
-                          char const *cacheName,
-                          unsigned long flags);
-    int writeCache();
-
-    /*
-     * Link the given bitcodes in mSource to shared object (.so).
-     *
-     * Currently, it requires one to provide the relocatable object files with
-     * given bitcodes to output a shared object.
-     *
-     * The usage of this function is flexible. You can have a relocatable object
-     * compiled before and pass it in objPath to generate shared object. If the
-     * objPath is NULL, we'll invoke prepareRelocatable() to get .o first (if
-     * you haven't done that yet) and then link the output relocatable object
-     * file to .so in dsoPath.
-     *
-     * TODO: Currently, we only support to link a bitcode (i.e., mSource.)
-     *
-     */
-    int prepareSharedObject(char const *objPath,
-                            char const *dsoPath,
-                            unsigned long flags);
-
-    int prepareRelocatable(char const *objPath,
-                           llvm::Reloc::Model RelocModel,
-                           unsigned long flags);
-
-    char const *getCompilerErrorMessage();
-
-    void *lookup(const char *name);
-
-    size_t getExportVarCount() const;
-
-    size_t getExportFuncCount() const;
-
-    size_t getExportForEachCount() const;
-
-    size_t getPragmaCount() const;
-
-    size_t getFuncCount() const;
-
-    size_t getObjectSlotCount() const;
-
-    void getExportVarList(size_t size, void **list);
-
-    void getExportFuncList(size_t size, void **list);
-
-    void getExportForEachList(size_t size, void **list);
-
-    void getExportVarNameList(std::vector<std::string> &list);
-
-    void getExportFuncNameList(std::vector<std::string> &list);
-
-    void getExportForEachNameList(std::vector<std::string> &list);
-
-    void getPragmaList(size_t size,
-                       char const **keyList,
-                       char const **valueList);
-
-    void getFuncInfoList(size_t size, FuncInfo *list);
-
-    void getObjectSlotList(size_t size, uint32_t *list);
-
-    size_t getELFSize() const;
-
-    const char *getELF() const;
-
-    int registerSymbolCallback(BCCSymbolLookupFn pFn, void *pContext);
-
-    bool isCacheable() const;
-
-    void setError(int error) {
-      if (mErrorCode == BCC_NO_ERROR && error != BCC_NO_ERROR) {
-        mErrorCode = error;
-      }
-    }
-
-    int getError() {
-      int result = mErrorCode;
-      mErrorCode = BCC_NO_ERROR;
-      return result;
-    }
-
-  private:
-    //
-    // It returns 0 if there's a cache hit.
-    //
-    // Side effect: it will set mCacheDir, mCacheName.
-    int internalLoadCache(char const *cacheDir, char const *cacheName,
-                          bool checkOnly);
-
-    int internalCompile(const CompilerOption&);
-  };
-
-} // namespace bcc
-
-#endif // BCC_EXECUTION_ENGINE_RS_SCRIPT_H
diff --git a/lib/ExecutionEngine/Script.cpp b/lib/ExecutionEngine/Script.cpp
index 785915c..7c79254 100644
--- a/lib/ExecutionEngine/Script.cpp
+++ b/lib/ExecutionEngine/Script.cpp
@@ -1,24 +1,105 @@
 /*
- * Copyright 2010-2012, The Android Open Source Project
+ * copyright 2010-2012, the android open source project
  *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
+ * licensed under the apache license, version 2.0 (the "license");
+ * you may not use this file except in compliance with the license.
+ * you may obtain a copy of the license at
  *
- *     http://www.apache.org/licenses/LICENSE-2.0
+ *     http://www.apache.org/licenses/license-2.0
  *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
+ * unless required by applicable law or agreed to in writing, software
+ * distributed under the license is distributed on an "as is" basis,
+ * without warranties or conditions of any kind, either express or implied.
+ * see the license for the specific language governing permissions and
+ * limitations under the license.
  */
 
 #include "Script.h"
 
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <new>
+#include <cstring>
+
+#include <llvm/ADT/STLExtras.h>
+
+#include <cutils/properties.h>
+
+#include "Config.h"
+
+#include "MCCacheReader.h"
+#include "MCCacheWriter.h"
+#include "CompilerOption.h"
+
+#include "BCCContextImpl.h"
+#include "DebugHelper.h"
+#include "FileHandle.h"
+#include "GDBJITRegistrar.h"
+#include "ScriptCompiled.h"
+#include "ScriptCached.h"
+#include "Sha1Helper.h"
 #include "Source.h"
 
-using namespace bcc;
+namespace {
+
+bool getBooleanProp(const char *str) {
+  char buf[PROPERTY_VALUE_MAX];
+  property_get(str, buf, "0");
+  return strcmp(buf, "0") != 0;
+}
+
+} // namespace anonymous
+
+namespace bcc {
+
+Script::Script(Source &pSource)
+  : mSource(&pSource),
+    mpExtSymbolLookupFn(NULL),
+    mpExtSymbolLookupFnContext(NULL) {
+  resetState();
+  return;
+}
+
+Script::~Script() {
+  switch (mStatus) {
+  case ScriptStatus::Compiled:
+    delete mCompiled;
+    break;
+
+  case ScriptStatus::Cached:
+    delete mCached;
+    break;
+
+  default:
+    break;
+  }
+  llvm::DeleteContainerPointers(mDependencyInfos);
+}
+
+void Script::resetState() {
+  mErrorCode = BCC_NO_ERROR;
+  mStatus = ScriptStatus::Unknown;
+  mObjectType = ScriptObject::Unknown;
+  mIsContextSlotNotAvail = false;
+  // FIXME: mpExtSymbolLookupFn and mpExtSymbolLookupFnContext should be assign
+  //        to NULL during state resetting.
+  //mpExtSymbolLookupFn = NULL;
+  //mpExtSymbolLookupFnContext = NULL;
+  llvm::DeleteContainerPointers(mDependencyInfos);
+  return;
+}
+
+
+Script::DependencyInfo::DependencyInfo(MCO_ResourceType pSourceType,
+                                       const std::string &pSourceName,
+                                       const uint8_t *pSHA1)
+  : mSourceType(pSourceType), mSourceName(pSourceName) {
+  ::memcpy(mSHA1, pSHA1, sizeof(mSHA1));
+  return;
+}
 
 bool Script::reset(Source &pSource, bool pPreserveCurrent) {
   if (mSource == &pSource) {
@@ -29,9 +110,636 @@
     delete mSource;
   }
   mSource = &pSource;
-  return doReset();
+  resetState();
+  return true;
 }
 
 bool Script::mergeSource(Source &pSource, bool pPreserveSource) {
   return mSource->merge(pSource, pPreserveSource);
 }
+
+bool Script::addSourceDependencyInfo(MCO_ResourceType pSourceType,
+                                     const std::string &pSourceName,
+                                     const uint8_t *pSHA1) {
+  DependencyInfo *dep_info = new (std::nothrow) DependencyInfo(pSourceType,
+                                                               pSourceName,
+                                                               pSHA1);
+  if (dep_info == NULL) {
+    ALOGE("Out of memory when record dependency information of `%s'!",
+          pSourceName.c_str());
+    return false;
+  }
+
+  mDependencyInfos.push_back(dep_info);
+  return true;
+}
+
+int Script::prepareRelocatable(char const *objPath,
+                               llvm::Reloc::Model RelocModel,
+                               unsigned long flags) {
+  CompilerOption option;
+  option.RelocModelOpt = RelocModel;
+  option.RunLTO = false;
+  option.LoadAfterCompile = false;
+
+  int status = internalCompile(option);
+  if (status != 0) {
+    ALOGE("LLVM error message: %s\n", getCompilerErrorMessage());
+    return status;
+  }
+
+  FileHandle objFile;
+  if (objFile.open(objPath, OpenMode::Write) < 0) {
+    ALOGE("Failed to open %s for write.\n", objPath);
+    return 1;
+  }
+
+  if (static_cast<size_t>(objFile.write(getELF(),
+                                        getELFSize())) != getELFSize()) {
+      objFile.close();
+      ::unlink(objPath);
+      ALOGE("Unable to write ELF to file %s.\n", objPath);
+      return false;
+  }
+
+  mObjectType = ScriptObject::Relocatable;
+
+  return 0;
+}
+
+
+int Script::prepareSharedObject(char const *objPath,
+                                char const *dsoPath,
+                                unsigned long flags) {
+  // TODO: Support cached shared object.
+  return 1;
+}
+
+
+int Script::prepareExecutable(char const *cacheDir,
+                              char const *cacheName,
+                              unsigned long flags) {
+  if (mStatus != ScriptStatus::Unknown) {
+    mErrorCode = BCC_INVALID_OPERATION;
+    ALOGE("Invalid operation: %s\n", __func__);
+    return 1;
+  }
+
+  int status = internalLoadCache(cacheDir, cacheName, /* checkOnly */ false);
+
+  if (status != 0) {
+    CompilerOption option;
+    status = internalCompile(option);
+
+    if (status != 0) {
+      ALOGE("LLVM error message: %s\n", getCompilerErrorMessage());
+      return status;
+    }
+
+    status = writeCache();
+    if (status != 0) {
+      ALOGE("Failed to write the cache for %s\n", cacheName);
+      return status;
+    }
+  }
+
+  // FIXME: Registration can be conditional on the presence of debug metadata
+  registerObjectWithGDB(getELF(), getELFSize()); // thread-safe registration
+
+  mObjectType = ScriptObject::Executable;
+
+  return status;
+}
+
+int Script::internalLoadCache(char const *cacheDir, char const *cacheName,
+                              bool checkOnly) {
+  if ((cacheDir == NULL) || (cacheName == NULL)) {
+    return 1;
+  }
+
+  // Set cache file Name
+  mCacheName = cacheName;
+
+  // Santize mCacheDir. Ensure that mCacheDir ends with '/'.
+  mCacheDir = cacheDir;
+  if (!mCacheDir.empty() && *mCacheDir.rbegin() != '/') {
+    mCacheDir.push_back('/');
+  }
+
+  if (!isCacheable()) {
+    return 1;
+  }
+
+  std::string objPath = getCachedObjectPath();
+  std::string infoPath = getCacheInfoPath();
+
+  FileHandle objFile;
+  if (objFile.open(objPath.c_str(), OpenMode::Read) < 0) {
+    // Unable to open the executable file in read mode.
+    return 1;
+  }
+
+  FileHandle infoFile;
+  if (infoFile.open(infoPath.c_str(), OpenMode::Read) < 0) {
+    // Unable to open the metadata information file in read mode.
+    return 1;
+  }
+
+  MCCacheReader reader;
+
+  // Register symbol lookup function
+  if (mpExtSymbolLookupFn) {
+    reader.registerSymbolCallback(mpExtSymbolLookupFn,
+                                      mpExtSymbolLookupFnContext);
+  }
+
+  // Dependencies
+  reader.addDependency(BCC_FILE_RESOURCE, pathLibBCC_SHA1, sha1LibBCC_SHA1);
+  reader.addDependency(BCC_FILE_RESOURCE, pathLibRS, sha1LibRS);
+
+  for (unsigned i = 0; i < mDependencyInfos.size(); i++) {
+    const DependencyInfo *dep_info = mDependencyInfos[i];
+    reader.addDependency(dep_info->getSourceType(),
+                         dep_info->getSourceName(),
+                         dep_info->getSHA1Checksum());
+  }
+
+  if (checkOnly)
+    return !reader.checkCacheFile(&objFile, &infoFile, this);
+
+  // Read cache file
+  ScriptCached *cached = reader.readCacheFile(&objFile, &infoFile, this);
+
+  if (!cached) {
+    mIsContextSlotNotAvail = reader.isContextSlotNotAvail();
+    return 1;
+  }
+
+  mCached = cached;
+  mStatus = ScriptStatus::Cached;
+
+  // Dirty hack for libRS.
+  // TODO(all):  This dirty hack should be removed in the future.
+  if (!cached->isLibRSThreadable() && mpExtSymbolLookupFn) {
+    mpExtSymbolLookupFn(mpExtSymbolLookupFnContext, "__clearThreadable");
+  }
+
+  return 0;
+}
+
+int Script::internalCompile(const CompilerOption &option) {
+  // Create the ScriptCompiled object
+  mCompiled = new (std::nothrow) ScriptCompiled(this);
+
+  if (!mCompiled) {
+    mErrorCode = BCC_OUT_OF_MEMORY;
+    ALOGE("Out of memory: %s %d\n", __FILE__, __LINE__);
+    return 1;
+  }
+
+  mStatus = ScriptStatus::Compiled;
+
+  // Register symbol lookup function
+  if (mpExtSymbolLookupFn) {
+    mCompiled->registerSymbolCallback(mpExtSymbolLookupFn,
+                                      mpExtSymbolLookupFnContext);
+  }
+
+  // Set the main source module
+  if (mCompiled->readModule(mSource->getModule()) != 0) {
+    ALOGE("Unable to read source module\n");
+    return 1;
+  }
+
+  // Compile and JIT the code
+  if (mCompiled->compile(option) != 0) {
+    ALOGE("Unable to compile.\n");
+    return 1;
+  }
+
+  return 0;
+}
+
+int Script::writeCache() {
+  // Not compiled script or encountered error during the compilation.
+  if ((mStatus != ScriptStatus::Compiled) ||
+      (getCompilerErrorMessage() == NULL))
+    return 1;
+
+  // Note: If we re-compile the script because the cached context slot not
+  // available, then we don't have to write the cache.
+
+  // Note: If the address of the context is not in the context slot, then
+  // we don't have to cache it.
+
+  if (isCacheable()) {
+
+    std::string objPath = getCachedObjectPath();
+    std::string infoPath = getCacheInfoPath();
+
+    // Remove the file if it already exists before writing the new file.
+    // The old file may still be mapped elsewhere in memory and we do not want
+    // to modify its contents.  (The same script may be running concurrently in
+    // the same process or a different process!)
+    ::unlink(objPath.c_str());
+    ::unlink(infoPath.c_str());
+
+    FileHandle objFile;
+    FileHandle infoFile;
+
+    if (objFile.open(objPath.c_str(), OpenMode::Write) >= 0 &&
+        infoFile.open(infoPath.c_str(), OpenMode::Write) >= 0) {
+
+      MCCacheWriter writer;
+
+#ifdef TARGET_BUILD
+      // Dependencies
+      writer.addDependency(BCC_FILE_RESOURCE, pathLibBCC_SHA1, sha1LibBCC_SHA1);
+      writer.addDependency(BCC_FILE_RESOURCE, pathLibRS, sha1LibRS);
+#endif
+
+      for (unsigned i = 0; i < mDependencyInfos.size(); i++) {
+        const DependencyInfo *dep_info = mDependencyInfos[i];
+        writer.addDependency(dep_info->getSourceType(),
+                             dep_info->getSourceName(),
+                             dep_info->getSHA1Checksum());
+      }
+
+
+      // libRS is threadable dirty hack
+      // TODO: This should be removed in the future
+      uint32_t libRS_threadable = 0;
+      if (mpExtSymbolLookupFn) {
+        libRS_threadable =
+          (uint32_t)mpExtSymbolLookupFn(mpExtSymbolLookupFnContext,
+                                        "__isThreadable");
+      }
+
+      if (!writer.writeCacheFile(&objFile, &infoFile, this, libRS_threadable)) {
+        objFile.truncate();
+        objFile.close();
+
+        if (unlink(objPath.c_str()) != 0) {
+          ALOGE("Unable to remove the invalid cache file: %s. (reason: %s)\n",
+               objPath.c_str(), strerror(errno));
+        }
+
+        infoFile.truncate();
+        infoFile.close();
+
+        if (unlink(infoPath.c_str()) != 0) {
+          ALOGE("Unable to remove the invalid cache file: %s. (reason: %s)\n",
+               infoPath.c_str(), strerror(errno));
+        }
+      }
+    }
+  }
+
+  return 0;
+}
+
+
+char const *Script::getCompilerErrorMessage() {
+  if (mStatus != ScriptStatus::Compiled) {
+    mErrorCode = BCC_INVALID_OPERATION;
+    return NULL;
+  }
+
+  return mCompiled->getCompilerErrorMessage();
+}
+
+
+void *Script::lookup(const char *name) {
+  switch (mStatus) {
+    case ScriptStatus::Compiled: {
+      return mCompiled->lookup(name);
+    }
+
+    case ScriptStatus::Cached: {
+      return mCached->lookup(name);
+    }
+
+    default: {
+      mErrorCode = BCC_INVALID_OPERATION;
+      return NULL;
+    }
+  }
+}
+
+
+size_t Script::getExportVarCount() const {
+  switch (mStatus) {
+    case ScriptStatus::Compiled: {
+      return mCompiled->getExportVarCount();
+    }
+
+    case ScriptStatus::Cached: {
+      return mCached->getExportVarCount();
+    }
+
+    default: {
+      return 0;
+    }
+  }
+}
+
+
+size_t Script::getExportFuncCount() const {
+  switch (mStatus) {
+    case ScriptStatus::Compiled: {
+      return mCompiled->getExportFuncCount();
+    }
+
+    case ScriptStatus::Cached: {
+      return mCached->getExportFuncCount();
+    }
+
+    default: {
+      return 0;
+    }
+  }
+}
+
+
+size_t Script::getExportForEachCount() const {
+  switch (mStatus) {
+    case ScriptStatus::Compiled: {
+      return mCompiled->getExportForEachCount();
+    }
+
+    case ScriptStatus::Cached: {
+      return mCached->getExportForEachCount();
+    }
+
+    default: {
+      return 0;
+    }
+  }
+}
+
+
+size_t Script::getPragmaCount() const {
+  switch (mStatus) {
+    case ScriptStatus::Compiled: {
+      return mCompiled->getPragmaCount();
+    }
+
+    case ScriptStatus::Cached: {
+      return mCached->getPragmaCount();
+    }
+
+    default: {
+      return 0;
+    }
+  }
+}
+
+
+size_t Script::getFuncCount() const {
+  switch (mStatus) {
+    case ScriptStatus::Compiled: {
+      return mCompiled->getFuncCount();
+    }
+
+    case ScriptStatus::Cached: {
+      return mCached->getFuncCount();
+    }
+
+    default: {
+      return 0;
+    }
+  }
+}
+
+
+size_t Script::getObjectSlotCount() const {
+  switch (mStatus) {
+    case ScriptStatus::Compiled: {
+      return mCompiled->getObjectSlotCount();
+    }
+
+    case ScriptStatus::Cached: {
+      return mCached->getObjectSlotCount();
+    }
+
+    default: {
+      return 0;
+    }
+  }
+}
+
+
+void Script::getExportVarList(size_t varListSize, void **varList) {
+  switch (mStatus) {
+#define DELEGATE(STATUS) \
+    case ScriptStatus::STATUS:                           \
+      m##STATUS->getExportVarList(varListSize, varList); \
+      break;
+
+    DELEGATE(Cached);
+
+    DELEGATE(Compiled);
+#undef DELEGATE
+
+    default: {
+      mErrorCode = BCC_INVALID_OPERATION;
+    }
+  }
+}
+
+void Script::getExportVarNameList(std::vector<std::string> &varList) {
+  switch (mStatus) {
+    case ScriptStatus::Compiled: {
+      return mCompiled->getExportVarNameList(varList);
+    }
+
+    default: {
+      mErrorCode = BCC_INVALID_OPERATION;
+    }
+  }
+}
+
+
+void Script::getExportFuncList(size_t funcListSize, void **funcList) {
+  switch (mStatus) {
+#define DELEGATE(STATUS) \
+    case ScriptStatus::STATUS:                              \
+      m##STATUS->getExportFuncList(funcListSize, funcList); \
+      break;
+
+    DELEGATE(Cached);
+
+    DELEGATE(Compiled);
+#undef DELEGATE
+
+    default: {
+      mErrorCode = BCC_INVALID_OPERATION;
+    }
+  }
+}
+
+void Script::getExportFuncNameList(std::vector<std::string> &funcList) {
+  switch (mStatus) {
+    case ScriptStatus::Compiled: {
+      return mCompiled->getExportFuncNameList(funcList);
+    }
+
+    default: {
+      mErrorCode = BCC_INVALID_OPERATION;
+    }
+  }
+}
+
+void Script::getExportForEachList(size_t funcListSize, void **funcList) {
+  switch (mStatus) {
+#define DELEGATE(STATUS) \
+    case ScriptStatus::STATUS:                                 \
+      m##STATUS->getExportForEachList(funcListSize, funcList); \
+      break;
+
+    DELEGATE(Cached);
+
+    DELEGATE(Compiled);
+#undef DELEGATE
+
+    default: {
+      mErrorCode = BCC_INVALID_OPERATION;
+    }
+  }
+}
+
+void Script::getExportForEachNameList(std::vector<std::string> &forEachList) {
+  switch (mStatus) {
+    case ScriptStatus::Compiled: {
+      return mCompiled->getExportForEachNameList(forEachList);
+    }
+
+    default: {
+      mErrorCode = BCC_INVALID_OPERATION;
+    }
+  }
+}
+
+void Script::getPragmaList(size_t pragmaListSize,
+                           char const **keyList,
+                           char const **valueList) {
+  switch (mStatus) {
+#define DELEGATE(STATUS) \
+    case ScriptStatus::STATUS:                                      \
+      m##STATUS->getPragmaList(pragmaListSize, keyList, valueList); \
+      break;
+
+    DELEGATE(Cached);
+
+    DELEGATE(Compiled);
+#undef DELEGATE
+
+    default: {
+      mErrorCode = BCC_INVALID_OPERATION;
+    }
+  }
+}
+
+
+void Script::getFuncInfoList(size_t funcInfoListSize,
+                             FuncInfo *funcInfoList) {
+  switch (mStatus) {
+#define DELEGATE(STATUS) \
+    case ScriptStatus::STATUS:                                    \
+      m##STATUS->getFuncInfoList(funcInfoListSize, funcInfoList); \
+      break;
+
+    DELEGATE(Cached);
+
+    DELEGATE(Compiled);
+#undef DELEGATE
+
+    default: {
+      mErrorCode = BCC_INVALID_OPERATION;
+    }
+  }
+}
+
+
+void Script::getObjectSlotList(size_t objectSlotListSize,
+                               uint32_t *objectSlotList) {
+  switch (mStatus) {
+#define DELEGATE(STATUS)     \
+    case ScriptStatus::STATUS:                                          \
+      m##STATUS->getObjectSlotList(objectSlotListSize, objectSlotList); \
+      break;
+
+    DELEGATE(Cached);
+
+    DELEGATE(Compiled);
+#undef DELEGATE
+
+    default: {
+      mErrorCode = BCC_INVALID_OPERATION;
+    }
+  }
+}
+
+
+int Script::registerSymbolCallback(BCCSymbolLookupFn pFn, void *pContext) {
+  mpExtSymbolLookupFn = pFn;
+  mpExtSymbolLookupFnContext = pContext;
+
+  if (mStatus != ScriptStatus::Unknown) {
+    mErrorCode = BCC_INVALID_OPERATION;
+    ALOGE("Invalid operation: %s\n", __func__);
+    return 1;
+  }
+  return 0;
+}
+
+bool Script::isCacheable() const {
+  if (getBooleanProp("debug.bcc.nocache")) {
+    // Android system environment property: Disables the cache mechanism by
+    // setting "debug.bcc.nocache".  So we will not load the cache file any
+    // way.
+    return false;
+  }
+
+  if (mCacheDir.empty() || mCacheName.empty()) {
+    // The application developer has not specified the cachePath, so
+    // we don't know where to open the cache file.
+    return false;
+  }
+
+  return true;
+}
+
+size_t Script::getELFSize() const {
+  switch (mStatus) {
+    case ScriptStatus::Compiled: {
+      return mCompiled->getELFSize();
+    }
+
+    case ScriptStatus::Cached: {
+      return mCached->getELFSize();
+    }
+
+    default: {
+      return 0;
+    }
+  }
+}
+
+const char *Script::getELF() const {
+  switch (mStatus) {
+    case ScriptStatus::Compiled: {
+      return mCompiled->getELF();
+    }
+
+    case ScriptStatus::Cached: {
+      return mCached->getELF();
+    }
+
+    default: {
+      return NULL;
+    }
+  }
+}
+
+} // namespace bcc
diff --git a/lib/ExecutionEngine/Script.h b/lib/ExecutionEngine/Script.h
index aaa5eba..b654797 100644
--- a/lib/ExecutionEngine/Script.h
+++ b/lib/ExecutionEngine/Script.h
@@ -14,49 +14,241 @@
  * limitations under the License.
  */
 
-#ifndef BCC_EXECUTION_ENGINE_SCRIPT_H
-#define BCC_EXECUTION_ENGINE_SCRIPT_H
+#ifndef BCC_SCRIPT_H
+#define BCC_SCRIPT_H
+
+#include <vector>
+#include <string>
+
+#include <stdint.h>
+#include <stddef.h>
+
+#include <llvm/ADT/SmallVector.h>
+
+#include <bcc/bcc.h>
+#include <bcc/bcc_mccache.h>
+#include "bcc_internal.h"
+
+#include "Compiler.h"
+
+namespace llvm {
+  class Module;
+  class GDBJITRegistrar;
+}
 
 namespace bcc {
+  class ScriptCompiled;
+  class ScriptCached;
+  class Source;
+  struct CompilerOption;
 
-class Source;
+  namespace ScriptStatus {
+    enum StatusType {
+      Unknown,
+      Compiled,
+      Cached
+    };
+  }
 
-class Script {
-private:
-  // This is the source associated with this object and is going to be
-  // compiled.
-  Source *mSource;
+  namespace ScriptObject {
+    enum ObjectType {
+      Unknown,
+      Relocatable,
+      SharedObject,
+      Executable,
+    };
+  }
 
-protected:
-  // This hook will be invoked after the script object is succssfully reset
-  // itself.
-  virtual bool doReset()
-  { return true; }
+  class Script {
+  private:
+    int mErrorCode;
 
-public:
-  Script(Source &pSource) : mSource(&pSource) { }
+    ScriptStatus::StatusType mStatus;
+    // The type of the object behind this script after compilation. For
+    // example, after returning from a successful call to prepareRelocatable(),
+    // the value of mObjectType will be ScriptObject::Relocatable.
+    ScriptObject::ObjectType mObjectType;
 
-  virtual ~Script() { }
+    union {
+      ScriptCompiled *mCompiled;
+      ScriptCached *mCached;
+    };
 
-  // Reset this object with the new source supplied. Return false if this
-  // object remains unchanged after the call (e.g., the supplied source is
-  // the same with the one contain in this object.) If pPreserveCurrent is
-  // false, the current containing source will be destroyed after successfully
-  // reset.
-  bool reset(Source &pSource, bool pPreserveCurrent = false);
+    std::string mCacheDir;
+    std::string mCacheName;
 
-  // Merge (or link) another source into the current source associated with
-  // this Script object. Return false on error.
-  //
-  // This is equivalent to the call to Script::merge(...) on mSource.
-  bool mergeSource(Source &pSource, bool pPreserveSource = false);
+    inline std::string getCachedObjectPath() const {
+      return std::string(mCacheDir + mCacheName + ".o");
+    }
 
-  inline Source &getSource()
-  { return *mSource; }
-  inline const Source &getSource() const
-  { return *mSource; }
-};
+    inline std::string getCacheInfoPath() const {
+      return getCachedObjectPath().append(".info");
+    }
 
-} // end namespace bcc
+    bool mIsContextSlotNotAvail;
 
-#endif  // BCC_EXECUTION_ENGINE_SCRIPT_H
+    // This is the source associated with this object and is going to be
+    // compiled.
+    Source *mSource;
+
+    class DependencyInfo {
+    private:
+      MCO_ResourceType mSourceType;
+      std::string mSourceName;
+      uint8_t mSHA1[20];
+
+    public:
+      DependencyInfo(MCO_ResourceType pSourceType,
+                     const std::string &pSourceName,
+                     const uint8_t *pSHA1);
+
+      inline MCO_ResourceType getSourceType() const
+      { return mSourceType; }
+
+      inline const std::string getSourceName() const
+      { return mSourceName; }
+
+      inline const uint8_t *getSHA1Checksum() const
+      { return mSHA1; }
+    };
+    llvm::SmallVector<DependencyInfo *, 2> mDependencyInfos;
+
+    // External Function List
+    std::vector<char const *> mUserDefinedExternalSymbols;
+
+    // Register Symbol Lookup Function
+    BCCSymbolLookupFn mpExtSymbolLookupFn;
+    void *mpExtSymbolLookupFnContext;
+
+    // Reset the state of this script object
+    void resetState();
+
+  public:
+    Script(Source &pSource);
+
+    ~Script();
+
+    // Reset this object with the new source supplied. Return false if this
+    // object remains unchanged after the call (e.g., the supplied source is
+    // the same with the one contain in this object.) If pPreserveCurrent is
+    // false, the current containing source will be destroyed after successfully
+    // reset.
+    bool reset(Source &pSource, bool pPreserveCurrent = false);
+
+    // Merge (or link) another source into the current source associated with
+    // this Script object. Return false on error.
+    bool mergeSource(Source &pSource, bool pPreserveSource = false);
+
+    // Add dependency information for this script given the source named
+    // pSourceName. pSHA1 is the SHA-1 checksum of the given source. Return
+    // false on error.
+    bool addSourceDependencyInfo(MCO_ResourceType pSourceType,
+                                 const std::string &pSourceName,
+                                 const uint8_t *pSHA1);
+
+    void markExternalSymbol(char const *name) {
+      mUserDefinedExternalSymbols.push_back(name);
+    }
+
+    std::vector<char const *> const &getUserDefinedExternalSymbols() const {
+      return mUserDefinedExternalSymbols;
+    }
+
+    int prepareExecutable(char const *cacheDir,
+                          char const *cacheName,
+                          unsigned long flags);
+    int writeCache();
+
+    /*
+     * Link the given bitcodes in mSource to shared object (.so).
+     *
+     * Currently, it requires one to provide the relocatable object files with
+     * given bitcodes to output a shared object.
+     *
+     * The usage of this function is flexible. You can have a relocatable object
+     * compiled before and pass it in objPath to generate shared object. If the
+     * objPath is NULL, we'll invoke prepareRelocatable() to get .o first (if
+     * you haven't done that yet) and then link the output relocatable object
+     * file to .so in dsoPath.
+     *
+     * TODO: Currently, we only support to link a bitcode (i.e., mSource.)
+     *
+     */
+    int prepareSharedObject(char const *objPath,
+                            char const *dsoPath,
+                            unsigned long flags);
+
+    int prepareRelocatable(char const *objPath,
+                           llvm::Reloc::Model RelocModel,
+                           unsigned long flags);
+
+    char const *getCompilerErrorMessage();
+
+    void *lookup(const char *name);
+
+    size_t getExportVarCount() const;
+
+    size_t getExportFuncCount() const;
+
+    size_t getExportForEachCount() const;
+
+    size_t getPragmaCount() const;
+
+    size_t getFuncCount() const;
+
+    size_t getObjectSlotCount() const;
+
+    void getExportVarList(size_t size, void **list);
+
+    void getExportFuncList(size_t size, void **list);
+
+    void getExportForEachList(size_t size, void **list);
+
+    void getExportVarNameList(std::vector<std::string> &list);
+
+    void getExportFuncNameList(std::vector<std::string> &list);
+
+    void getExportForEachNameList(std::vector<std::string> &list);
+
+    void getPragmaList(size_t size,
+                       char const **keyList,
+                       char const **valueList);
+
+    void getFuncInfoList(size_t size, FuncInfo *list);
+
+    void getObjectSlotList(size_t size, uint32_t *list);
+
+    size_t getELFSize() const;
+
+    const char *getELF() const;
+
+    int registerSymbolCallback(BCCSymbolLookupFn pFn, void *pContext);
+
+    bool isCacheable() const;
+
+    void setError(int error) {
+      if (mErrorCode == BCC_NO_ERROR && error != BCC_NO_ERROR) {
+        mErrorCode = error;
+      }
+    }
+
+    int getError() {
+      int result = mErrorCode;
+      mErrorCode = BCC_NO_ERROR;
+      return result;
+    }
+
+  private:
+    //
+    // It returns 0 if there's a cache hit.
+    //
+    // Side effect: it will set mCacheDir, mCacheName.
+    int internalLoadCache(char const *cacheDir, char const *cacheName,
+                          bool checkOnly);
+
+    int internalCompile(const CompilerOption&);
+  };
+
+} // namespace bcc
+
+#endif // BCC_SCRIPT_H
diff --git a/lib/ExecutionEngine/ScriptCompiled.h b/lib/ExecutionEngine/ScriptCompiled.h
index e96dbe2..8752aa3 100644
--- a/lib/ExecutionEngine/ScriptCompiled.h
+++ b/lib/ExecutionEngine/ScriptCompiled.h
@@ -26,7 +26,7 @@
 #include <bcc/bcc.h>
 
 #include "Compiler.h"
-#include "RSScript.h"
+#include "Script.h"
 
 namespace llvm {
   class Module;
@@ -48,7 +48,7 @@
     typedef std::list<uint32_t> ObjectSlotList;
 
   private:
-    RSScript *mpOwner;
+    Script *mpOwner;
 
     Compiler mCompiler;
 
@@ -66,7 +66,7 @@
     FuncInfoMap mEmittedFunctions;
 
   public:
-    ScriptCompiled(RSScript *owner)
+    ScriptCompiled(Script *owner)
       : mpOwner(owner), mCompiler(this)
     {
     }
diff --git a/lib/ExecutionEngine/bcc.cpp b/lib/ExecutionEngine/bcc.cpp
index 7425d0a..ee6efaa 100644
--- a/lib/ExecutionEngine/bcc.cpp
+++ b/lib/ExecutionEngine/bcc.cpp
@@ -31,7 +31,7 @@
 #include "BCCContext.h"
 #include "Compiler.h"
 #include "DebugHelper.h"
-#include "RSScript.h"
+#include "Script.h"
 #include "Sha1Helper.h"
 #include "Source.h"
 
@@ -62,7 +62,7 @@
   }
 
   Source *source = Source::CreateEmpty(*context, "empty");
-  return wrap(new RSScript(*source));
+  return wrap(new Script(*source));
 }
 
 
@@ -85,7 +85,7 @@
   return unwrap(script)->getError();
 }
 
-static bool helper_add_source(RSScript *pScript,
+static bool helper_add_source(Script *pScript,
                               char const *pName,
                               char const *pBitcode,
                               size_t pBitcodeSize,
@@ -114,7 +114,7 @@
   if (need_dependency_check) {
     uint8_t sha1[20];
     calcSHA1(sha1, pBitcode, pBitcodeSize);
-    if (!pScript->addSourceDependency(BCC_APK_RESOURCE, pName, sha1)) {
+    if (!pScript->addSourceDependencyInfo(BCC_APK_RESOURCE, pName, sha1)) {
       return false;
     }
   }
@@ -122,7 +122,7 @@
   return ((pIsLink) ? pScript->mergeSource(*source) : pScript->reset(*source));
 }
 
-static bool helper_add_source(RSScript *pScript,
+static bool helper_add_source(Script *pScript,
                               llvm::Module *pModule,
                               bool pIsLink) {
   if (pModule == NULL)
@@ -146,7 +146,7 @@
   return ((pIsLink) ? pScript->mergeSource(*source) : pScript->reset(*source));
 }
 
-static bool helper_add_source(RSScript *pScript,
+static bool helper_add_source(Script *pScript,
                               char const *pPath,
                               unsigned long pFlags,
                               bool pIsLink) {
@@ -164,7 +164,7 @@
   if (need_dependency_check) {
     uint8_t sha1[20];
     calcFileSHA1(sha1, pPath);
-    if (!pScript->addSourceDependency(BCC_APK_RESOURCE, pPath, sha1)) {
+    if (!pScript->addSourceDependencyInfo(BCC_APK_RESOURCE, pPath, sha1)) {
       return false;
     }
   }
diff --git a/lib/ExecutionEngine/bcc_internal.h b/lib/ExecutionEngine/bcc_internal.h
index 553034c..d0f5766 100644
--- a/lib/ExecutionEngine/bcc_internal.h
+++ b/lib/ExecutionEngine/bcc_internal.h
@@ -35,7 +35,7 @@
 }
 
 namespace bcc {
-  class RSScript;
+  class Script;
 
   /* Function information struct */
   struct FuncInfo {
@@ -44,7 +44,7 @@
     size_t size;
   };
 
-  BCC_OPAQUE_TYPE_CONVERSION(bcc::RSScript *, BCCScriptRef);
+  BCC_OPAQUE_TYPE_CONVERSION(bcc::Script *, BCCScriptRef);
   BCC_OPAQUE_TYPE_CONVERSION(llvm::Module *, LLVMModuleRef);
 
 } // namespace bcc