Add mBccCodeAddrTaken. Now BCC_CODE_ADDR should always be defined.
mBccCodeAddrTaken functions as the knob now.

Change-Id: I5b2475bb49fe9a91c25910ba1aa6f4b201da6148
diff --git a/bcc.cpp b/bcc.cpp
index d44d241..8e9371c 100644
--- a/bcc.cpp
+++ b/bcc.cpp
@@ -18,7 +18,7 @@
 //    This is an eager-compilation JIT running on Android.
 
 // Fixed BCC_CODE_ADDR here only works for 1 cached EXE.
-// So when mLoaded == 1, will set mCacheNever to true.
+// At most 1 live Compiler object will have set mBccCodeAddrTaken
 #define BCC_CODE_ADDR 0x7e00000
 
 #define LOG_TAG "bcc"
@@ -299,6 +299,7 @@
   // is initialized in GlobalInitialization()
   //
   static bool GlobalInitialized;
+  //sliao  static bool BccCodeAddrTaken;
 
   // If given, this will be the name of the target triple to compile for.
   // If not given, the initial values defined in this file will be used.
@@ -451,6 +452,7 @@
   ptrdiff_t mCacheDiff;   // Set by loader()
   char *mCodeDataAddr;    // Set by CodeMemoryManager if mCacheNew is true.
                           // Used by genCacheFile() for dumping
+  bool mBccCodeAddrTaken;
 
   typedef std::list< std::pair<std::string, std::string> > PragmaList;
   PragmaList mPragmas;
@@ -567,21 +569,24 @@
       reset();
       std::string ErrMsg;
 
-#ifdef BCC_CODE_ADDR
+      //      if (!Compiler::BccCodeAddrTaken) {  // Use BCC_CODE_ADDR
       mpCodeMem = mmap(reinterpret_cast<void*>(BCC_CODE_ADDR),
                        MaxCodeSize + MaxGlobalVarSize,
                        PROT_READ | PROT_EXEC | PROT_WRITE,
                        MAP_PRIVATE | MAP_ANON | MAP_FIXED,
                        -1,
                        0);
-#else
-      mpCodeMem = mmap(NULL,
-                       MaxCodeSize + MaxGlobalVarSize,
-                       PROT_READ | PROT_EXEC | PROT_WRITE,
-                       MAP_PRIVATE | MAP_ANON,
-                       -1,
-                       0);
-#endif
+
+      if (mpCodeMem == MAP_FAILED) {
+        mpCodeMem = mmap(NULL,
+                         MaxCodeSize + MaxGlobalVarSize,
+                         PROT_READ | PROT_EXEC | PROT_WRITE,
+                         MAP_PRIVATE | MAP_ANON,
+                         -1,
+                         0);
+      } else {
+        //        mBccCodeAddrTaken = true;
+      }
 
       if (mpCodeMem == MAP_FAILED) {
         llvm::report_fatal_error("Failed to allocate memory for emitting "
@@ -2510,6 +2515,7 @@
         mCacheSize(0),
         mCacheDiff(0),
         mCodeDataAddr(NULL),
+        mBccCodeAddrTaken(false),
         mpSymbolLookupFn(NULL),
         mpSymbolLookupContext(NULL),
         mContext(NULL),
@@ -2611,7 +2617,6 @@
       goto giveup;
     }
 
-
     // Check File Size
     struct stat statCacheFd;
     if (fstat(mCacheFd, &statCacheFd) < 0) {
@@ -2634,37 +2639,19 @@
 
     // Read File Content
     {
-#ifdef BCC_CODE_ADDR
+      // Part 1. Deal with the non-codedata section first
       off_t heuristicCodeOffset = mCacheSize - MaxCodeSize - MaxGlobalVarSize;
-
-      mCodeDataAddr = (char *) mmap(reinterpret_cast<void*>(BCC_CODE_ADDR),
-                                    MaxCodeSize + MaxGlobalVarSize,
-                                    PROT_READ | PROT_EXEC | PROT_WRITE,
-                                    MAP_PRIVATE | MAP_FIXED,
-                                    mCacheFd, heuristicCodeOffset);
       LOGE("sliao@Loader: mCacheSize=%x, heuristicCodeOffset=%x", mCacheSize, heuristicCodeOffset);
-      LOGE("sliao@Loader: mCodeDataAddr=%x", mCodeDataAddr);
-
-      if (mCodeDataAddr == MAP_FAILED) {
-        LOGE("unable to mmap .oBBC cache code/data: %s\n", strerror(errno));
-        flock(mCacheFd, LOCK_UN);
-        goto giveup;
-      }
 
       mCacheMapAddr = (char *)malloc(heuristicCodeOffset);
-
       if (!mCacheMapAddr) {
-        flock(mCacheFd, LOCK_UN);
-        LOGE("allocation failed.\n");
-        // TODO(all)
-        goto bail;
+          flock(mCacheFd, LOCK_UN);
+          LOGE("allocation failed.\n");
+          goto bail;
       }
 
       size_t nread = TEMP_FAILURE_RETRY1(read(mCacheFd, mCacheMapAddr,
                                               heuristicCodeOffset));
-
-      flock(mCacheFd, LOCK_UN);
-
       if (nread != (size_t)heuristicCodeOffset) {
         LOGE("read(mCacheFd) failed\n");
         free(mCacheMapAddr);
@@ -2672,183 +2659,188 @@
       }
 
       mCacheHdr = reinterpret_cast<oBCCHeader *>(mCacheMapAddr);
+      // Sanity check
+      if (mCacheHdr->codeOffset != (uint32_t)heuristicCodeOffset) {
+        LOGE("assertion failed: heuristic code offset is not correct.\n");
+        goto bail;
+      }
       LOGE("sliao: mCacheHdr->cachedCodeDataAddr=%x", mCacheHdr->cachedCodeDataAddr);
       LOGE("mCacheHdr->rootAddr=%x", mCacheHdr->rootAddr);
       LOGE("mCacheHdr->initAddr=%x", mCacheHdr->initAddr);
       LOGE("mCacheHdr->codeOffset=%x", mCacheHdr->codeOffset);
       LOGE("mCacheHdr->codeSize=%x", mCacheHdr->codeSize);
 
-      if (mCacheHdr->codeOffset != (uint32_t)heuristicCodeOffset) {
-        LOGE("assertion failed: heuristic code offset is not correct.\n");
+      // Verify the Cache File
+      if (memcmp(mCacheHdr->magic, OBCC_MAGIC, 4) != 0) {
+        LOGE("bad magic word\n");
         goto bail;
       }
-#else
-      mCacheMapAddr = (char *) mmap(0, mCacheSize,
-                                    PROT_READ | PROT_EXEC | PROT_WRITE,
-                                    MAP_PRIVATE, mCacheFd, 0);
 
-      if (mCacheMapAddr == MAP_FAILED) {
-        LOGE("unable to mmap .oBBC cache: %s\n", strerror(errno));
-        flock(mCacheFd, LOCK_UN);
-        goto giveup;
+      if (memcmp(mCacheHdr->magicVersion, OBCC_MAGIC_VERS, 4) != 0) {
+        LOGE("bad oBCC version 0x%08x\n",
+             *reinterpret_cast<uint32_t *>(mCacheHdr->magicVersion));
+        goto bail;
       }
 
-      flock(mCacheFd, LOCK_UN);
+      if (mCacheSize < mCacheHdr->relocOffset +
+          mCacheHdr->relocCount * sizeof(oBCCRelocEntry)) {
+        LOGE("relocate table overflow\n");
+        goto bail;
+      }
 
-      mCacheHdr = reinterpret_cast<oBCCHeader *>(mCacheMapAddr);
+      if (mCacheSize < mCacheHdr->exportVarsOffset +
+          mCacheHdr->exportVarsCount * sizeof(uint32_t)) {
+        LOGE("export variables table overflow\n");
+        goto bail;
+      }
 
-      mCodeDataAddr = mCacheMapAddr + mCacheHdr->codeOffset;
-#endif
+      if (mCacheSize < mCacheHdr->exportFuncsOffset +
+          mCacheHdr->exportFuncsCount * sizeof(uint32_t)) {
+        LOGE("export functions table overflow\n");
+        goto bail;
+      }
+
+      if (mCacheSize < mCacheHdr->exportPragmasOffset +
+          mCacheHdr->exportPragmasCount * sizeof(uint32_t)) {
+        LOGE("export pragmas table overflow\n");
+        goto bail;
+      }
+
+      if (mCacheSize < mCacheHdr->codeOffset + mCacheHdr->codeSize) {
+        LOGE("code cache overflow\n");
+        goto bail;
+      }
+
+      if (mCacheSize < mCacheHdr->dataOffset + mCacheHdr->dataSize) {
+        LOGE("data (global variable) cache overflow\n");
+        goto bail;
+      }
+
+      // Part 2. Deal with the codedata section
+      mCodeDataAddr = (char *) mmap(reinterpret_cast<void*>(BCC_CODE_ADDR),
+                                    MaxCodeSize + MaxGlobalVarSize,
+                                    PROT_READ | PROT_EXEC | PROT_WRITE,
+                                    MAP_PRIVATE | MAP_FIXED,
+                                    mCacheFd, heuristicCodeOffset);
+      if (mCodeDataAddr != MAP_FAILED &&
+          mCodeDataAddr ==
+          reinterpret_cast<char *>(mCacheHdr->cachedCodeDataAddr)) {
+        // relocate is avoidable
+        mBccCodeAddrTaken = true;
+
+        flock(mCacheFd, LOCK_UN);
+      } else {
+        mCacheMapAddr = (char *) mmap(0,
+                                      mCacheSize,
+                                      PROT_READ | PROT_EXEC | PROT_WRITE,
+                                      MAP_PRIVATE,
+                                      mCacheFd,
+                                      0);
+        if (mCacheMapAddr == MAP_FAILED) {
+          LOGE("unable to mmap .oBBC cache: %s\n", strerror(errno));
+          flock(mCacheFd, LOCK_UN);
+          goto giveup;
+        }
+
+        flock(mCacheFd, LOCK_UN);
+        mCodeDataAddr = mCacheMapAddr + mCacheHdr->codeOffset;
+      }
     }
 
-
-    // Verify the Cache File
-    if (memcmp(mCacheHdr->magic, OBCC_MAGIC, 4) != 0) {
-      LOGE("bad magic word\n");
-      goto bail;
-    }
-
-    if (memcmp(mCacheHdr->magicVersion, OBCC_MAGIC_VERS, 4) != 0) {
-      LOGE("bad oBCC version 0x%08x\n",
-               *reinterpret_cast<uint32_t *>(mCacheHdr->magicVersion));
-      goto bail;
-    }
-
-    if (mCacheSize < mCacheHdr->relocOffset +
-                     mCacheHdr->relocCount * sizeof(oBCCRelocEntry)) {
-      LOGE("relocate table overflow\n");
-      goto bail;
-    }
-
-    if (mCacheSize < mCacheHdr->exportVarsOffset +
-                     mCacheHdr->exportVarsCount * sizeof(uint32_t)) {
-      LOGE("export variables table overflow\n");
-      goto bail;
-    }
-
-    if (mCacheSize < mCacheHdr->exportFuncsOffset +
-                     mCacheHdr->exportFuncsCount * sizeof(uint32_t)) {
-      LOGE("export functions table overflow\n");
-      goto bail;
-    }
-
-    if (mCacheSize < mCacheHdr->exportPragmasOffset +
-                     mCacheHdr->exportPragmasCount * sizeof(uint32_t)) {
-      LOGE("export pragmas table overflow\n");
-      goto bail;
-    }
-
-    if (mCacheSize < mCacheHdr->codeOffset + mCacheHdr->codeSize) {
-      LOGE("code cache overflow\n");
-      goto bail;
-    }
-
-    if (mCacheSize < mCacheHdr->dataOffset + mCacheHdr->dataSize) {
-      LOGE("data (global variable) cache overflow\n");
-      goto bail;
-    }
-
-
     // Relocate
     {
       mCacheDiff = mCodeDataAddr -
                    reinterpret_cast<char *>(mCacheHdr->cachedCodeDataAddr);
 
-#ifdef BCC_CODE_ADDR
-      if (mCacheDiff != 0) {
-        LOGE("mCacheDiff should be zero but mCacheDiff = %d\n", mCacheDiff);
-        goto bail;
-      }
-#else
-      if (mCacheHdr->rootAddr) {
-        mCacheHdr->rootAddr += mCacheDiff;
-      }
-
-      if (mCacheHdr->initAddr) {
-        mCacheHdr->initAddr += mCacheDiff;
-      }
-
-      oBCCRelocEntry *cachedRelocTable =
-        reinterpret_cast<oBCCRelocEntry *>(mCacheMapAddr +
-                                           mCacheHdr->relocOffset);
-
-      std::vector<llvm::MachineRelocation> relocations;
-
-      // Read in the relocs
-      for (size_t i = 0; i < mCacheHdr->relocCount; i++) {
-        oBCCRelocEntry *entry = &cachedRelocTable[i];
-
-        llvm::MachineRelocation reloc =
-          llvm::MachineRelocation::getGV((uintptr_t)entry->relocOffset,
-                                         (unsigned)entry->relocType, 0, 0);
-
-        reloc.setResultPointer(
-          reinterpret_cast<char *>(entry->cachedResultAddr) + mCacheDiff);
-
-        relocations.push_back(reloc);
-      }
-
-      // Rewrite machine code using llvm::TargetJITInfo relocate
-      {
-        llvm::TargetMachine *TM = NULL;
-        const llvm::Target *Target;
-        std::string FeaturesStr;
-
-        // Create TargetMachine
-        Target = llvm::TargetRegistry::lookupTarget(Triple, mError);
-        if (hasError())
-          goto bail;
-
-        if (!CPU.empty() || !Features.empty()) {
-          llvm::SubtargetFeatures F;
-          F.setCPU(CPU);
-          for (std::vector<std::string>::const_iterator I = Features.begin(),
-                  E = Features.end(); I != E; I++)
-            F.AddFeature(*I);
-          FeaturesStr = F.getString();
+      if (!mBccCodeAddrTaken) {  // To relocate
+        if (mCacheHdr->rootAddr) {
+          mCacheHdr->rootAddr += mCacheDiff;
         }
 
-        TM = Target->createTargetMachine(Triple, FeaturesStr);
-        if (TM == NULL) {
-          setError("Failed to create target machine implementation for the"
-                   " specified triple '" + Triple + "'");
-          goto bail;
+        if (mCacheHdr->initAddr) {
+          mCacheHdr->initAddr += mCacheDiff;
         }
 
-        TM->getJITInfo()->relocate(mCodeDataAddr,
-                                   &relocations[0], relocations.size(),
-                                   (unsigned char *)mCodeDataAddr+MaxCodeSize);
+        oBCCRelocEntry *cachedRelocTable =
+            reinterpret_cast<oBCCRelocEntry *>(mCacheMapAddr +
+                                               mCacheHdr->relocOffset);
 
-        if (mCodeEmitter.get()) {
-          mCodeEmitter->Disassemble(llvm::StringRef("cache"),
-                                    reinterpret_cast<uint8_t*>(mCodeDataAddr),
-                                    2 * 1024 /*MaxCodeSize*/,
-                                    false);
+        std::vector<llvm::MachineRelocation> relocations;
+
+        // Read in the relocs
+        for (size_t i = 0; i < mCacheHdr->relocCount; i++) {
+          oBCCRelocEntry *entry = &cachedRelocTable[i];
+
+          llvm::MachineRelocation reloc =
+              llvm::MachineRelocation::getGV((uintptr_t)entry->relocOffset,
+                                             (unsigned)entry->relocType, 0, 0);
+
+          reloc.setResultPointer(
+              reinterpret_cast<char *>(entry->cachedResultAddr) + mCacheDiff);
+
+          relocations.push_back(reloc);
         }
 
-        delete TM;
-      }
-#endif
+        // Rewrite machine code using llvm::TargetJITInfo relocate
+        {
+          llvm::TargetMachine *TM = NULL;
+          const llvm::Target *Target;
+          std::string FeaturesStr;
+
+          // Create TargetMachine
+          Target = llvm::TargetRegistry::lookupTarget(Triple, mError);
+          if (hasError())
+            goto bail;
+
+          if (!CPU.empty() || !Features.empty()) {
+            llvm::SubtargetFeatures F;
+            F.setCPU(CPU);
+            for (std::vector<std::string>::const_iterator I = Features.begin(),
+                     E = Features.end(); I != E; I++)
+              F.AddFeature(*I);
+            FeaturesStr = F.getString();
+          }
+
+          TM = Target->createTargetMachine(Triple, FeaturesStr);
+          if (TM == NULL) {
+            setError("Failed to create target machine implementation for the"
+                     " specified triple '" + Triple + "'");
+            goto bail;
+          }
+
+          TM->getJITInfo()->relocate(mCodeDataAddr,
+                                     &relocations[0], relocations.size(),
+                                     (unsigned char *)mCodeDataAddr+MaxCodeSize);
+
+          if (mCodeEmitter.get()) {
+            mCodeEmitter->Disassemble(llvm::StringRef("cache"),
+                                      reinterpret_cast<uint8_t*>(mCodeDataAddr),
+                                      2 * 1024 /*MaxCodeSize*/,
+                                      false);
+          }
+
+          delete TM;
+        }
+      }  // End of if (!mBccCodeAddrTaken)
     }
 
     return 0;
 
-  bail:
-#ifdef BCC_CODE_ADDR
-    if (munmap(mCodeDataAddr, MaxCodeSize + MaxGlobalVarSize) != 0) {
-      LOGE("munmap failed: %s\n", strerror(errno));
-    }
-
+ bail:
     if (mCacheMapAddr) {
       free(mCacheMapAddr);
     }
-#else
-    if (munmap(mCacheMapAddr, mCacheSize) != 0) {
-      LOGE("munmap failed: %s\n", strerror(errno));
+    if (mBccCodeAddrTaken) {
+      if (munmap(mCodeDataAddr, MaxCodeSize + MaxGlobalVarSize) != 0) {
+        LOGE("munmap failed: %s\n", strerror(errno));
+      }
+    } else {
+      if (munmap(mCacheMapAddr, mCacheSize) != 0) {
+        LOGE("munmap failed: %s\n", strerror(errno));
+      }
     }
-#endif
 
-  giveup:
+ giveup:
     return 1;
   }
 
@@ -3335,23 +3327,21 @@
   }
 
   ~Compiler() {
-#ifdef BCC_CODE_ADDR
+    // #ifdef BCC_CODE_ADDR
     if (mCodeDataAddr != 0 && mCodeDataAddr != MAP_FAILED) {
       if (munmap(mCodeDataAddr, MaxCodeSize + MaxGlobalVarSize) < 0) {
         LOGE("munmap failed while releasing mCodeDataAddr\n");
       }
-    }
-
-    if (mCacheMapAddr) {
-      free(mCacheMapAddr);
-    }
-#else
-    if (mCacheMapAddr != 0 && mCacheMapAddr != MAP_FAILED) {
-      if (munmap(mCacheMapAddr, mCacheSize) < 0) {
-        LOGE("munmap failed while releasing mCacheMapAddr\n");
+      if (mCacheMapAddr) {
+        free(mCacheMapAddr);
+      }
+    } else {
+      if (mCacheMapAddr != 0 && mCacheMapAddr != MAP_FAILED) {
+        if (munmap(mCacheMapAddr, mCacheSize) < 0) {
+          LOGE("munmap failed while releasing mCacheMapAddr\n");
+        }
       }
     }
-#endif
 
     delete mModule;
     // llvm::llvm_shutdown();
@@ -3420,8 +3410,8 @@
 
     // Code Offset and Size
 
-#ifdef BCC_CODE_ADDR
-    {
+    //#ifdef BCC_CODE_ADDR
+    {  // Always pad to the page boundary for now
       long pagesize = sysconf(_SC_PAGESIZE);
 
       if (offset % pagesize > 0) {
@@ -3429,12 +3419,12 @@
         offset += pagesize - (offset % pagesize);
       }
     }
-#else
+    /*#else
     if (offset & 0x07) { // Ensure that offset aligned to 64-bit (8 byte).
       codeOffsetNeedPadding = true;
       offset += 0x08 - (offset & 0x07);
     }
-#endif
+    #endif*/
 
     hdr->codeOffset = offset;
     hdr->codeSize = MaxCodeSize;