Add modify time and crc32 to bccReadBC and cache header.
diff --git a/lib/bcc/Compiler.cpp b/lib/bcc/Compiler.cpp
index 6b36507..fcd92a3 100644
--- a/lib/bcc/Compiler.cpp
+++ b/lib/bcc/Compiler.cpp
@@ -310,6 +310,8 @@
     mUseCache(false),
     mCacheNew(false),
     mCacheFd(-1),
+    mSourceModTime(0),
+    mSourceCRC32(0),
     mCacheMapAddr(NULL),
     mCacheHdr(NULL),
     mCacheSize(0),
@@ -336,6 +338,8 @@
 
 int Compiler::readBC(const char *bitcode,
                      size_t bitcodeSize,
+                     long bitcodeFileModTime,
+                     long bitcodeFileCRC32,
                      const BCCchar *resName,
                      const BCCchar *cacheDir) {
   GlobalInitialization();
@@ -374,6 +378,11 @@
     resName = NULL;
   }
 
+  // Assign bitcodeFileModTime to mSourceModTime, and bitcodeFileCRC32 to
+  // mSourceCRC32, so that the checkHeaderAndDependencies can use them.
+  mSourceModTime = bitcodeFileModTime;
+  mSourceCRC32 = bitcodeFileCRC32;
+
   if (resName) {
     // Turn on mUseCache mode iff
     // 1. Has resName
@@ -1364,21 +1373,28 @@
   memcpy(hdr->magicVersion, OBCC_MAGIC_VERS, 4);
 
   // Timestamp
-  // TODO(sliao): Should be .bc's ModifyTime. Now just use it to store
-  //              threadable
-  hdr->sourceWhen = (uint32_t) mCodeEmitter->mpSymbolLookupFn(
-      mpSymbolLookupContext,
-      "__isThreadable");
-
+  hdr->sourceWhen = mSourceModTime;
   hdr->rslibWhen = 0; // TODO(sliao)
   hdr->libRSWhen = statModifyTime(libRSPath);
   hdr->libbccWhen = statModifyTime(libBccPath);
 
+  // Source Bitcode File CRC32
+  hdr->sourceCRC32 = mSourceCRC32;
+
   // Current Memory Address (Saved for Recalculation)
   hdr->cachedCodeDataAddr = reinterpret_cast<uint32_t>(mCodeDataAddr);
   hdr->rootAddr = reinterpret_cast<uint32_t>(lookup("root"));
   hdr->initAddr = reinterpret_cast<uint32_t>(lookup("init"));
 
+  // Check libRS isThreadable
+  if (!mCodeEmitter) {
+    hdr->libRSThreadable = 0;
+  } else {
+    hdr->libRSThreadable =
+      (uint32_t) mCodeEmitter->mpSymbolLookupFn(mpSymbolLookupContext,
+                                                "__isThreadable");
+  }
+
   // Relocation Table Offset and Entry Count
   hdr->relocOffset = sizeof(oBCCHeader);
   hdr->relocCount = mCodeEmitter->getCachingRelocations().size();
@@ -1671,7 +1687,7 @@
   } else {
     // Calculate sourceWhen
     // XXX
-    uint32_t sourceWhen = 0;
+    long sourceWhen = mSourceModTime;
     uint32_t rslibWhen = 0;
     uint32_t libRSWhen = statModifyTime(libRSPath);
     uint32_t libbccWhen = statModifyTime(libBccPath);
@@ -1800,101 +1816,91 @@
  * oBCC header.
  */
 bool Compiler::checkHeaderAndDependencies(int fd,
-                                          uint32_t sourceWhen,
+                                          long sourceWhen,
                                           uint32_t rslibWhen,
                                           uint32_t libRSWhen,
                                           uint32_t libbccWhen) {
-  ssize_t actual;
   oBCCHeader optHdr;
-  uint32_t val;
-  uint8_t const *magic, *magicVer;
 
-  /*
-   * Start at the start.  The "bcc" header, when present, will always be
-   * the first thing in the file.
-   */
+  // The header is guaranteed to be at the start of the cached file.
+  // Seek to the start position.
   if (lseek(fd, 0, SEEK_SET) != 0) {
     LOGE("bcc: failed to seek to start of file: %s\n", strerror(errno));
-    goto bail;
+    return false;
   }
 
-  /*
-   * Read and do trivial verification on the bcc header.  The header is
-   * always in host byte order.
-   */
-  actual = read(fd, &optHdr, sizeof(optHdr));
-  if (actual < 0) {
+  // Read and do trivial verification on the bcc header.  The header is
+  // always in host byte order.
+  ssize_t nread = read(fd, &optHdr, sizeof(optHdr));
+  if (nread < 0) {
     LOGE("bcc: failed reading bcc header: %s\n", strerror(errno));
-    goto bail;
-  } else if (actual != sizeof(optHdr)) {
+    return false;
+  } else if (nread != sizeof(optHdr)) {
     LOGE("bcc: failed reading bcc header (got %d of %zd)\n",
-         (int) actual, sizeof(optHdr));
-    goto bail;
+         (int) nread, sizeof(optHdr));
+    return false;
   }
 
-  magic = optHdr.magic;
+  uint8_t const *magic = optHdr.magic;
   if (memcmp(magic, OBCC_MAGIC, 4) != 0) {
     /* not an oBCC file, or previous attempt was interrupted */
     LOGD("bcc: incorrect opt magic number (0x%02x %02x %02x %02x)\n",
          magic[0], magic[1], magic[2], magic[3]);
-    goto bail;
+    return false;
   }
 
-  magicVer = optHdr.magicVersion;
+  uint8_t const *magicVer = optHdr.magicVersion;
   if (memcmp(magicVer, OBCC_MAGIC_VERS, 4) != 0) {
     LOGW("bcc: stale oBCC version (0x%02x %02x %02x %02x)\n",
          magicVer[0], magicVer[1], magicVer[2], magicVer[3]);
-    goto bail;
+    return false;
   }
 
-  /*
-   * Do the header flags match up with what we want?
-   *
-   * This is useful because it allows us to automatically regenerate
-   * a file when settings change (e.g. verification is now mandatory),
-   * but can cause difficulties if the thing we depend upon
-   * were handled differently than the current options specify.
-   *
-   * So, for now, we essentially ignore "expectVerify" and "expectOpt"
-   * by limiting the match mask.
-   *
-   * The only thing we really can't handle is incorrect byte-ordering.
-   */
+  // Check the file dependencies
 
-  val = optHdr.sourceWhen;
-  // TODO(sliao): Shouldn't overload sourceWhen in the future.
-  if (!val) {
-    mpSymbolLookupFn(mpSymbolLookupContext, "__clearThreadable");
+  if (optHdr.sourceWhen && (optHdr.sourceWhen != sourceWhen)) {
+    LOGI("bcc: source file mod time mismatch (%08lx vs %08lx)\n",
+         (unsigned long)optHdr.sourceWhen, (unsigned long)sourceWhen);
+    return false;
   }
-  //  if (val && (val != sourceWhen)) {
-  //    LOGI("bcc: source file mod time mismatch (%08x vs %08x)\n",
-  //         val, sourceWhen);
-  //    goto bail;
-  //  }
+
+  uint32_t val;
 
   val = optHdr.rslibWhen;
   if (val && (val != rslibWhen)) {
     LOGI("bcc: rslib file mod time mismatch (%08x vs %08x)\n",
          val, rslibWhen);
-    goto bail;
+    return false;
   }
+
   val = optHdr.libRSWhen;
   if (val && (val != libRSWhen)) {
     LOGI("bcc: libRS file mod time mismatch (%08x vs %08x)\n",
          val, libRSWhen);
-    goto bail;
+    return false;
   }
+
   val = optHdr.libbccWhen;
   if (val && (val != libbccWhen)) {
     LOGI("bcc: libbcc file mod time mismatch (%08x vs %08x)\n",
          val, libbccWhen);
-    goto bail;
+    return false;
+  }
+
+  // Check the CRC32 of the file
+  if (optHdr.sourceCRC32 && optHdr.sourceCRC32 != mSourceCRC32) {
+    LOGI("bcc: libbcc bitcode file crc32 mismatch (%08lx vs %08lx)\n",
+         optHdr.sourceCRC32, mSourceCRC32);
+    return false;
+  }
+
+  // Check the cache file has __isThreadable or not.  If it is present,
+  // then we have to call mpSymbolLookupFn for __clearThreadable.
+  if (optHdr.libRSThreadable && mpSymbolLookupFn) {
+    mpSymbolLookupFn(mpSymbolLookupContext, "__clearThreadable");
   }
 
   return true;
-
-bail:
-  return false;
 }
 
 }  // namespace bcc
diff --git a/lib/bcc/Compiler.h b/lib/bcc/Compiler.h
index 21f0bd4..fba7a01 100644
--- a/lib/bcc/Compiler.h
+++ b/lib/bcc/Compiler.h
@@ -95,6 +95,8 @@
     bool mUseCache;         // Set by readBC()
     bool mCacheNew;         // Set by readBC()
     int mCacheFd;           // Set by readBC()
+    long mSourceModTime;    // Set by readBC()
+    long mSourceCRC32;      // Set by readBC();
     char *mCacheMapAddr;    // Set by loadCacheFile() if mCacheNew is false
     oBCCHeader *mCacheHdr;  // Set by loadCacheFile()
     size_t mCacheSize;      // Set by loadCacheFile()
@@ -143,6 +145,8 @@
 
     int readBC(const char *bitcode,
                size_t bitcodeSize,
+               long bitcodeFileModTime,
+               long bitcodeFileCRC32,
                const BCCchar *resName,
                const BCCchar *cacheDir);
 
@@ -223,7 +227,7 @@
      * oBCC header.
      */
     bool checkHeaderAndDependencies(int fd,
-                                    uint32_t sourceWhen,
+                                    long sourceWhen,
                                     uint32_t rslibWhen,
                                     uint32_t libRSWhen,
                                     uint32_t libbccWhen);
diff --git a/lib/bcc/bcc.cpp b/lib/bcc/bcc.cpp
index ca4c880..149139c 100644
--- a/lib/bcc/bcc.cpp
+++ b/lib/bcc/bcc.cpp
@@ -57,10 +57,14 @@
 
 extern "C" int bccReadBC(BCCscript *script,
                          const BCCchar *bitcode,
-                         BCCint size,
+                         BCCint bitcodeSize,
+                         long bitcodeFileModTime,
+                         long bitcodeFileCRC32,
                          const BCCchar *resName,
                          const BCCchar *cacheDir) {
-  return script->compiler.readBC(bitcode, size, resName, cacheDir);
+  return script->compiler.readBC(bitcode, bitcodeSize,
+                                 bitcodeFileModTime, bitcodeFileCRC32,
+                                 resName, cacheDir);
 }
 
 extern "C" void bccLinkBC(BCCscript *script,