Add context manager (which manages code and data block of each script.)
diff --git a/lib/bcc/CodeMemoryManager.cpp b/lib/bcc/CodeMemoryManager.cpp
index 774ddc3..87b99c1 100644
--- a/lib/bcc/CodeMemoryManager.cpp
+++ b/lib/bcc/CodeMemoryManager.cpp
@@ -18,15 +18,14 @@
 #include <cutils/log.h>
 
 #include "CodeMemoryManager.h"
+#include "ContextManager.h"
 
 #include "llvm/Support/ErrorHandling.h"
 
-#include <errno.h>
 #include <sys/mman.h>
 
 #include <assert.h>
 #include <stddef.h>
-#include <string.h>
 
 #include <map>
 #include <string>
@@ -36,9 +35,9 @@
 namespace bcc {
 
 
-const unsigned int MaxCodeSize = BCC_MMAP_IMG_CODE_SIZE;
+const unsigned int MaxCodeSize = BCC_CONTEXT_CODE_SIZE;
 const unsigned int MaxGOTSize = 1 * 1024;
-const unsigned int MaxGlobalVarSize = BCC_MMAP_IMG_DATA_SIZE;
+const unsigned int MaxGlobalVarSize = BCC_CONTEXT_DATA_SIZE;
 
 
 CodeMemoryManager::CodeMemoryManager()
@@ -47,72 +46,26 @@
   reset();
   std::string ErrMsg;
 
-  // Try to use fixed address
+  mpCodeMem = allocateContext();
 
-  // Note: If we failed to allocate mpCodeMem at fixed address,
-  // the caching mechanism has to either perform relocation or
-  // give up.  If the caching mechanism gives up, then we have to
-  // recompile the bitcode and wasting a lot of time.
-
-  for (size_t i = 0; i < BCC_MMAP_IMG_COUNT; ++i) {
-    if (Compiler::BccMmapImgAddrTaken[i]) {
-      // The address BCC_MMAP_IMG_BEGIN + i * BCC_MMAP_IMG_SIZE has
-      // been taken.
-      continue;
-    }
-
-    // Occupy the mmap image address first (No matter allocation
-    // success or not.  Keep occupying if succeed; otherwise,
-    // keep occupying as a mark of failure.)
-    Compiler::BccMmapImgAddrTaken[i] = true;
-
-    void *currMmapImgAddr =
-      reinterpret_cast<void *>(BCC_MMAP_IMG_BEGIN + i * BCC_MMAP_IMG_SIZE);
-
-    mpCodeMem = mmap(currMmapImgAddr, BCC_MMAP_IMG_SIZE,
-                     PROT_READ | PROT_EXEC | PROT_WRITE,
-                     MAP_PRIVATE | MAP_ANON | MAP_FIXED,
-                     -1, 0);
-
-    if (mpCodeMem == MAP_FAILED) {
-      LOGE("Mmap mpCodeMem at %p failed with reason: %s. Retrying ..\n",
-           currMmapImgAddr, strerror(errno));
-    } else {
-      // Good, we have got one mmap image address.
-      break;
-    }
+  if (!mpCodeMem) {
+    LOGE("Unable to allocate mpCodeMem\n");
+    llvm::report_fatal_error("Failed to allocate memory for emitting "
+                             "codes\n" + ErrMsg);
   }
 
-  if (!mpCodeMem || mpCodeMem == MAP_FAILED) {
-    LOGE("Try to allocate mpCodeMem at arbitary address.\n");
-
-    mpCodeMem = mmap(NULL, BCC_MMAP_IMG_SIZE,
-                     PROT_READ | PROT_EXEC | PROT_WRITE,
-                     MAP_PRIVATE | MAP_ANON,
-                     -1, 0);
-
-    if (mpCodeMem == MAP_FAILED) {
-      LOGE("Unable to mmap mpCodeMem with reason: %s.\n", strerror(errno));
-      llvm::report_fatal_error("Failed to allocate memory for emitting "
-                               "codes\n" + ErrMsg);
-    }
-  }
-
-  LOGI("Mmap mpCodeMem at %p successfully.\n", mpCodeMem);
+  LOGI("Allocate mpCodeMem at %p successfully.\n", mpCodeMem);
 
   // Set global variable pool
-  mpGVMem = (void *) ((char *)mpCodeMem + MaxCodeSize);
+  mpGVMem = mpCodeMem + MaxCodeSize;
 
   return;
 }
 
 
 CodeMemoryManager::~CodeMemoryManager() {
-  if (mpCodeMem && mpCodeMem != MAP_FAILED) {
-    munmap(mpCodeMem, BCC_MMAP_IMG_SIZE);
-
-    // TODO(logan): Reset Compiler::BccMmapImgAddrTaken[i] to false, so
-    // that the address can be reused.
+  if (mpCodeMem) {
+    deallocateContext(mpCodeMem);
   }
 
   mpCodeMem = 0;
diff --git a/lib/bcc/CodeMemoryManager.h b/lib/bcc/CodeMemoryManager.h
index 2c147df..a5e3915 100644
--- a/lib/bcc/CodeMemoryManager.h
+++ b/lib/bcc/CodeMemoryManager.h
@@ -103,8 +103,8 @@
     uintptr_t mCurFuncMemIdx;
     uintptr_t mCurSGMemIdx;
     uintptr_t mCurGVMemIdx;
-    void *mpCodeMem;
-    void *mpGVMem;
+    char *mpCodeMem;
+    char *mpGVMem;
 
     // GOT Base
     uint8_t *mpGOTBase;
diff --git a/lib/bcc/Compiler.cpp b/lib/bcc/Compiler.cpp
index 695d1da..4a1a3ca 100644
--- a/lib/bcc/Compiler.cpp
+++ b/lib/bcc/Compiler.cpp
@@ -65,6 +65,8 @@
 
 #include "Compiler.h"
 
+#include "ContextManager.h"
+
 #include "llvm/ADT/StringRef.h"
 
 #include "llvm/Analysis/Passes.h"
@@ -98,7 +100,6 @@
 
 #include <errno.h>
 #include <sys/file.h>
-#include <sys/mman.h>
 #include <sys/stat.h>
 #include <sys/types.h>
 #include <unistd.h>
@@ -160,8 +161,6 @@
 
 bool Compiler::GlobalInitialized = false;
 
-bool Compiler::BccMmapImgAddrTaken[BCC_MMAP_IMG_COUNT];
-
 // Code generation optimization level for the compiler
 llvm::CodeGenOpt::Level Compiler::CodeGenOptLevel;
 
@@ -527,56 +526,38 @@
     long pagesize = sysconf(_SC_PAGESIZE);
 
     if (mCacheHdr->cachedCodeDataAddr % pagesize == 0) {
-      void *addr = reinterpret_cast<char *>(mCacheHdr->cachedCodeDataAddr);
+      char *addr = reinterpret_cast<char *>(mCacheHdr->cachedCodeDataAddr);
 
-      // Try to mmap at cached address directly.
-      mCodeDataAddr = (char *) mmap(addr,
-                                    BCC_MMAP_IMG_SIZE,
-                                    PROT_READ | PROT_EXEC | PROT_WRITE,
-                                    MAP_PRIVATE | MAP_FIXED,
-                                    mCacheFd,
-                                    mCacheHdr->codeOffset);
+      // Try to allocate context at cached address directly.
+      mCodeDataAddr = allocateContext(addr, mCacheFd, mCacheHdr->codeOffset);
 
-      if (mCodeDataAddr && mCodeDataAddr != MAP_FAILED) {
-        // Cheers!  Mapped at the cached address successfully.
-
-        // Update the BccMmapImgAddrTaken table (if required)
-        if (mCacheHdr->cachedCodeDataAddr >= BCC_MMAP_IMG_BEGIN) {
-          size_t offset = mCacheHdr->cachedCodeDataAddr - BCC_MMAP_IMG_BEGIN;
-          size_t scriptId = offset / BCC_MMAP_IMG_SIZE;
-
-          if ((offset % BCC_MMAP_IMG_SIZE) == 0 &&
-              scriptId < BCC_MMAP_IMG_COUNT) {
-            if (Compiler::BccMmapImgAddrTaken[scriptId] == true) {
-              mCodeDataAddr = (char *) MAP_FAILED;
-            } else {
-              Compiler::BccMmapImgAddrTaken[scriptId] = true;
-            }
-          }
-        }
+      if (!mCodeDataAddr) {
+        // Unable to allocate at cached address.  Give up.
+        flock(mCacheFd, LOCK_UN);
+        goto bail;
+      }
 
 #if 1
-        // Check the checksum of code and data
-        {
-          uint32_t sum = mCacheHdr->checksum;
-          uint32_t *ptr = (uint32_t *)mCodeDataAddr;
+      // Check the checksum of code and data
+      {
+        uint32_t sum = mCacheHdr->checksum;
+        uint32_t *ptr = (uint32_t *)mCodeDataAddr;
 
-          for (size_t i = 0; i < BCC_MMAP_IMG_SIZE / sizeof(uint32_t); ++i) {
-            sum ^= *ptr++;
-          }
-
-          if (sum != 0) {
-            LOGE("Checksum check failed\n");
-            goto bail;
-          }
-
-          LOGI("Passed checksum even parity verification.\n");
+        for (size_t i = 0; i < BCC_CONTEXT_SIZE / sizeof(uint32_t); ++i) {
+          sum ^= *ptr++;
         }
+
+        if (sum != 0) {
+          LOGE("Checksum check failed\n");
+          goto bail;
+        }
+
+        LOGI("Passed checksum even parity verification.\n");
+      }
 #endif
 
-        flock(mCacheFd, LOCK_UN);
-        return 0; // loadCacheFile succeed!
-      }
+      flock(mCacheFd, LOCK_UN);
+      return 0; // loadCacheFile succeed!
     }
   }
 
@@ -699,10 +680,8 @@
     free(mCacheMapAddr);
   }
 
-  if (mCodeDataAddr && mCodeDataAddr != MAP_FAILED) {
-    if (munmap(mCodeDataAddr, BCC_MMAP_IMG_SIZE) != 0) {
-      LOGE("munmap failed: %s\n", strerror(errno));
-    }
+  if (mCodeDataAddr) {
+    deallocateContext(mCodeDataAddr);
   }
 
   mCacheMapAddr = NULL;
@@ -1210,10 +1189,8 @@
     // mCodeDataAddr and mCacheMapAddr are from loadCacheFile and not
     // managed by CodeMemoryManager.
 
-    if (mCodeDataAddr != 0 && mCodeDataAddr != MAP_FAILED) {
-      if (munmap(mCodeDataAddr, BCC_MMAP_IMG_SIZE) < 0) {
-        LOGE("munmap failed while releasing mCodeDataAddr\n");
-      }
+    if (mCodeDataAddr) {
+      deallocateContext(mCodeDataAddr);
     }
 
     if (mCacheMapAddr) {
@@ -1393,7 +1370,7 @@
     uint32_t sum = 0;
     uint32_t *ptr = (uint32_t *)mCodeDataAddr;
 
-    for (size_t i = 0; i < BCC_MMAP_IMG_SIZE / sizeof(uint32_t); ++i) {
+    for (size_t i = 0; i < BCC_CONTEXT_SIZE / sizeof(uint32_t); ++i) {
       sum ^= *ptr++;
     }
 
diff --git a/lib/bcc/Compiler.h b/lib/bcc/Compiler.h
index 444d136..ff9f0d6 100644
--- a/lib/bcc/Compiler.h
+++ b/lib/bcc/Compiler.h
@@ -34,14 +34,6 @@
 #include <utility>
 
 
-#define BCC_MMAP_IMG_BEGIN 0x7e000000
-#define BCC_MMAP_IMG_COUNT 5
-
-#define BCC_MMAP_IMG_CODE_SIZE (128 * 1024)
-#define BCC_MMAP_IMG_DATA_SIZE (128 * 1024)
-#define BCC_MMAP_IMG_SIZE (BCC_MMAP_IMG_CODE_SIZE + BCC_MMAP_IMG_DATA_SIZE)
-
-
 namespace llvm {
   class LLVMContext;
   class Module;
@@ -67,8 +59,6 @@
     //
     static bool GlobalInitialized;
 
-    static bool BccMmapImgAddrTaken[BCC_MMAP_IMG_COUNT];
-
     // 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.
     static std::string Triple;
diff --git a/lib/bcc/ContextManager.cpp b/lib/bcc/ContextManager.cpp
new file mode 100644
index 0000000..897314c
--- /dev/null
+++ b/lib/bcc/ContextManager.cpp
@@ -0,0 +1,144 @@
+/*
+ * copyright 2010, 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.
+ */
+
+#define LOG_TAG "bcc"
+#include <cutils/log.h>
+
+#include "ContextManager.h"
+
+#include <errno.h>
+#include <sys/mman.h>
+
+#include <stddef.h>
+#include <string.h>
+
+
+namespace {
+  static bool ContextSlotTaken[BCC_CONTEXT_SLOT_COUNT];
+} // namespace anonymous
+
+
+namespace bcc {
+
+char *allocateContext() {
+  // Try to allocate context on the managed context slot.
+  for (size_t i = 0; i < BCC_CONTEXT_SLOT_COUNT; ++i) {
+    if (ContextSlotTaken[i]) {
+      continue;
+    }
+
+    // Take the context slot.  (No matter we can mmap or not)
+    ContextSlotTaken[i] = true;
+
+    void *addr = BCC_CONTEXT_FIXED_ADDR + BCC_CONTEXT_SIZE * i;
+
+    // Try to mmap
+    void *result = mmap(addr, BCC_CONTEXT_SIZE,
+                        PROT_READ | PROT_WRITE | PROT_EXEC,
+                        MAP_PRIVATE | MAP_ANON | MAP_FIXED, -1, 0);
+
+    if (result && result != MAP_FAILED) { // Allocated successfully
+      return (char *)result;
+    }
+
+    LOGE("Unable to mmap at %p.  Retry ...\n", addr);
+  }
+
+  // No slot available, allocate at arbitary address.
+
+  void *result = mmap(0, BCC_CONTEXT_SIZE,
+                      PROT_READ | PROT_WRITE | PROT_EXEC,
+                      MAP_PRIVATE | MAP_ANON, -1, 0);
+
+  if (!result || result == MAP_FAILED) {
+    LOGE("Unable to mmap.  (reason: %s)\n", strerror(errno));
+    return NULL;
+  }
+
+  return (char *)result;
+}
+
+
+char *allocateContext(char *addr, int imageFd, off_t imageOffset) {
+  // This function should only allocate context when address is an context
+  // slot address.  And the image offset is aligned to the pagesize.
+
+  if (imageFd < 0) {
+    // Invalid file descriptor.
+    return NULL;
+  }
+
+  unsigned long pagesize = (unsigned long)sysconf(_SC_PAGESIZE);
+
+  if (imageOffset % pagesize > 0) {
+    // Image is not aligned in the cache file.
+    return NULL;
+  }
+
+  if (addr < BCC_CONTEXT_FIXED_ADDR) {
+    // If the suggest address is not at the context slot, then return
+    // NULL as error.
+    return NULL;
+  }
+
+  size_t offset = (size_t)(addr - BCC_CONTEXT_FIXED_ADDR);
+  size_t slot = offset / BCC_CONTEXT_SIZE;
+
+  if (offset % BCC_CONTEXT_SIZE != 0 || slot >= BCC_CONTEXT_SLOT_COUNT) {
+    // Invalid Slot Address (Not aligned or overflow)
+    return NULL;
+  }
+
+  if (ContextSlotTaken[slot]) {
+    // Slot has been taken.
+    return NULL;
+  }
+
+  ContextSlotTaken[slot] = true;
+
+  void *result = mmap(addr, BCC_CONTEXT_SIZE,
+                      PROT_READ | PROT_WRITE | PROT_EXEC,
+                      MAP_PRIVATE, imageFd, imageOffset);
+
+  return (result && result != MAP_FAILED) ? (char *)result : NULL;
+}
+
+
+void deallocateContext(char *addr) {
+  if (!addr) {
+    return;
+  }
+
+  // Unmap
+  if (munmap(addr, BCC_CONTEXT_SIZE) < 0) {
+    LOGE("Unable to unmap addr %p (reason: %s)\n", addr, strerror(errno));
+    return;
+  }
+
+  // If the address is one of the context slot, then mark such slot
+  // freely available as well.
+  if (addr >= BCC_CONTEXT_FIXED_ADDR) {
+    size_t offset = (size_t)(addr - BCC_CONTEXT_FIXED_ADDR);
+    size_t slot = offset / BCC_CONTEXT_SIZE;
+
+    if (offset % BCC_CONTEXT_SIZE == 0 && slot < BCC_CONTEXT_SLOT_COUNT) {
+      // Give the context slot back.
+      ContextSlotTaken[slot] = false;
+    }
+  }
+}
+
+} // namespace bcc
diff --git a/lib/bcc/ContextManager.h b/lib/bcc/ContextManager.h
new file mode 100644
index 0000000..b6d1a4c
--- /dev/null
+++ b/lib/bcc/ContextManager.h
@@ -0,0 +1,44 @@
+/*
+ * copyright 2010, 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_CONTEXTMANAGER_H
+#define BCC_CONTEXTMANAGER_H
+
+#include <stddef.h>
+
+#include <unistd.h>
+
+
+#define BCC_CONTEXT_FIXED_ADDR (reinterpret_cast<char *>(0x7e000000))
+#define BCC_CONTEXT_SLOT_COUNT 8 
+
+#define BCC_CONTEXT_CODE_SIZE (128 * 1024)
+#define BCC_CONTEXT_DATA_SIZE (128 * 1024)
+#define BCC_CONTEXT_SIZE (BCC_CONTEXT_CODE_SIZE + BCC_CONTEXT_DATA_SIZE)
+
+
+namespace bcc {
+
+  extern char *allocateContext();
+
+  extern char *allocateContext(char *addr, int imageFd, off_t imageOffset);
+
+  extern void deallocateContext(char *addr);
+
+} // namespace bcc
+
+
+#endif // BCC_CONTEXTMANAGER_H