Make the compiler threadsafe

The compiler inherited a simple memory management scheme that
involved malloc'ng a clump of memory, allocating out of that
clump for each unit of compilation, and then resetting after
the compilation was complete.  Simple & fast, but built with the
expectation of a single compiler worker thread.

This change moves the memory allocation arena into the
CompilationUnit structure, and makes it private for each method
compilation.  Unlike the old scheme, allocated memory is returned
to the system following completion (whereas before it was reused
for the next compilation).

As of this CL, each compilation is completely independent.

The changes involved were mostly mechanical to pass around the
cUnit pointer to anything which might need to allocate, but the
accretion of crud has moved me much closer to the point that
all of this stuff gets ripped out and replaced.

Change-Id: I19dda0a7fb5aa228f6baee7ae5293fdd174c8337
diff --git a/src/compiler/Compiler.h b/src/compiler/Compiler.h
index 909ac96..c09da33 100644
--- a/src/compiler/Compiler.h
+++ b/src/compiler/Compiler.h
@@ -159,7 +159,7 @@
 struct GrowableList;
 struct MIR;
 
-void oatInit(const Compiler& compiler);
+void oatInit(CompilationUnit* cUnit, const Compiler& compiler);
 bool oatArchInit(void);
 void oatArchDump(void);
 bool oatStartup(void);
@@ -182,10 +182,11 @@
 /* Clear the visited flag for each BB */
 bool oatClearVisitedFlag(struct CompilationUnit* cUnit,
                                  struct BasicBlock* bb);
-char* oatGetDalvikDisassembly(const DecodedInstruction* insn,
-                                      const char* note);
-char* oatFullDisassembler(const struct CompilationUnit* cUnit,
-                                  const struct MIR* mir);
+char* oatGetDalvikDisassembly(CompilationUnit* cUnit,
+                              const DecodedInstruction* insn,
+                              const char* note);
+char* oatFullDisassembler(struct CompilationUnit* cUnit,
+                          const struct MIR* mir);
 char* oatGetSSAString(struct CompilationUnit* cUnit,
                               struct SSARepresentation* ssaRep);
 void oatDataFlowAnalysisDispatcher(struct CompilationUnit* cUnit,
diff --git a/src/compiler/CompilerIR.h b/src/compiler/CompilerIR.h
index b17855b..720a31a 100644
--- a/src/compiler/CompilerIR.h
+++ b/src/compiler/CompilerIR.h
@@ -196,6 +196,8 @@
 
 struct LoopAnalysis;
 struct RegisterPool;
+struct ArenaMemBlock;
+struct Memstats;
 
 typedef enum AssemblerStatus {
     kSuccess,
@@ -330,6 +332,12 @@
      std::map<unsigned int, BasicBlock*> blockMap; // findBlock lookup cache
      std::map<unsigned int, LIR*> boundaryMap; // boundary lookup cache
      int defCount;         // Used to estimate number of SSA names
+     std::string* compilerMethodMatch;
+     bool compilerFlipMatch;
+     struct ArenaMemBlock* arenaHead;
+     struct ArenaMemBlock* currentArena;
+     int numArenaBlocks;
+     struct Memstats* mstats;
 } CompilationUnit;
 
 BasicBlock* oatNewBB(CompilationUnit* cUnit, BBType blockType, int blockId);
diff --git a/src/compiler/CompilerUtility.h b/src/compiler/CompilerUtility.h
index ba449a4..a6ddd1e 100644
--- a/src/compiler/CompilerUtility.h
+++ b/src/compiler/CompilerUtility.h
@@ -22,10 +22,10 @@
 namespace art {
 
 /* Each arena page has some overhead, so take a few bytes off */
-#define ARENA_DEFAULT_SIZE ((256 * 1024) - 256)
+#define ARENA_DEFAULT_SIZE ((2 * 1024 * 1024) - 256)
 
 /* Allocate the initial memory block for arena-based allocation */
-bool oatHeapInit(void);
+bool oatHeapInit(CompilationUnit* cUnit);
 
 /* Collect memory usage statstics */
 //#define WITH_MEMSTATS
@@ -37,9 +37,10 @@
     char ptr[0];
 } ArenaMemBlock;
 
-void* oatNew(size_t size, bool zero, oatAllocKind kind = kAllocMisc);
+void* oatNew(CompilationUnit* cUnit, size_t size, bool zero,
+             oatAllocKind kind = kAllocMisc);
 
-void oatArenaReset(void);
+void oatArenaReset(CompilationUnit *cUnit);
 
 typedef struct GrowableList {
     size_t numAllocated;
@@ -87,21 +88,23 @@
 struct BasicBlock;
 struct CompilationUnit;
 
-void oatInitGrowableList(GrowableList* gList, size_t initLength,
-                         oatListKind kind = kListMisc);
-void oatInsertGrowableList(GrowableList* gList, intptr_t elem);
+void oatInitGrowableList(CompilationUnit* cUnit,GrowableList* gList,
+                         size_t initLength, oatListKind kind = kListMisc);
+void oatInsertGrowableList(CompilationUnit* cUnit, GrowableList* gList,
+                           intptr_t elem);
 void oatDeleteGrowableList(GrowableList* gList, intptr_t elem);
 void oatGrowableListIteratorInit(GrowableList* gList,
                                  GrowableListIterator* iterator);
 intptr_t oatGrowableListIteratorNext(GrowableListIterator* iterator);
 intptr_t oatGrowableListGetElement(const GrowableList* gList, size_t idx);
 
-ArenaBitVector* oatAllocBitVector(unsigned int startBits, bool expandable,
+ArenaBitVector* oatAllocBitVector(CompilationUnit* cUnit,
+                                  unsigned int startBits, bool expandable,
                                   oatBitMapKind = kBitMapMisc);
 void oatBitVectorIteratorInit(ArenaBitVector* pBits,
                               ArenaBitVectorIterator* iterator);
 int oatBitVectorIteratorNext(ArenaBitVectorIterator* iterator);
-bool oatSetBit(ArenaBitVector* pBits, unsigned int num);
+bool oatSetBit(CompilationUnit *cUnit, ArenaBitVector* pBits, unsigned int num);
 bool oatClearBit(ArenaBitVector* pBits, unsigned int num);
 void oatMarkAllBits(ArenaBitVector* pBits, bool set);
 void oatDebugBitVector(char* msg, const ArenaBitVector* bv, int length);
diff --git a/src/compiler/Dataflow.cc b/src/compiler/Dataflow.cc
index cd63290..908e1cc 100644
--- a/src/compiler/Dataflow.cc
+++ b/src/compiler/Dataflow.cc
@@ -29,7 +29,7 @@
  * TODO - many optimization flags are incomplete - they will only limit the
  * scope of optimizations but will not cause mis-optimizations.
  */
-int oatDataFlowAttributes[kMirOpLast] = {
+const int oatDataFlowAttributes[kMirOpLast] = {
     // 00 OP_NOP
     DF_NOP,
 
@@ -819,8 +819,8 @@
  * and subscript pair. Each SSA register can be used to index the
  * ssaToDalvikMap list to get the subscript[31..16]/dalvik_reg[15..0] mapping.
  */
-char* oatGetDalvikDisassembly(const DecodedInstruction* insn,
-                                      const char* note)
+char* oatGetDalvikDisassembly(CompilationUnit* cUnit,
+                              const DecodedInstruction* insn, const char* note)
 {
     char buffer[256];
     Opcode opcode = insn->opcode;
@@ -900,7 +900,7 @@
         }
     }
     int length = strlen(buffer) + 1;
-    ret = (char*)oatNew(length, false, kAllocDFInfo);
+    ret = (char*)oatNew(cUnit, length, false, kAllocDFInfo);
     memcpy(ret, buffer, length);
     return ret;
 }
@@ -917,8 +917,8 @@
 /*
  * Dalvik instruction disassembler with optional SSA printing.
  */
-char* oatFullDisassembler(const CompilationUnit* cUnit,
-                                  const MIR* mir)
+char* oatFullDisassembler(CompilationUnit* cUnit,
+                          const MIR* mir)
 {
     char buffer[256];
     char operand0[32], operand1[32];
@@ -1036,7 +1036,7 @@
 
 done:
     length = strlen(buffer) + 1;
-    ret = (char*) oatNew(length, false, kAllocDFInfo);
+    ret = (char*) oatNew(cUnit, length, false, kAllocDFInfo);
     memcpy(ret, buffer, length);
     return ret;
 }
@@ -1078,25 +1078,27 @@
     }
 
     int length = strlen(buffer) + 1;
-    ret = (char*)oatNew(length, false, kAllocDFInfo);
+    ret = (char*)oatNew(cUnit, length, false, kAllocDFInfo);
     memcpy(ret, buffer, length);
     return ret;
 }
 
 /* Any register that is used before being defined is considered live-in */
-STATIC inline void handleLiveInUse(ArenaBitVector* useV, ArenaBitVector* defV,
+STATIC inline void handleLiveInUse(CompilationUnit* cUnit, ArenaBitVector* useV,
+                                   ArenaBitVector* defV,
                                    ArenaBitVector* liveInV, int dalvikRegId)
 {
-    oatSetBit(useV, dalvikRegId);
+    oatSetBit(cUnit, useV, dalvikRegId);
     if (!oatIsBitSet(defV, dalvikRegId)) {
-        oatSetBit(liveInV, dalvikRegId);
+        oatSetBit(cUnit, liveInV, dalvikRegId);
     }
 }
 
 /* Mark a reg as being defined */
-STATIC inline void handleDef(ArenaBitVector* defV, int dalvikRegId)
+STATIC inline void handleDef(CompilationUnit* cUnit, ArenaBitVector* defV,
+                             int dalvikRegId)
 {
-    oatSetBit(defV, dalvikRegId);
+    oatSetBit(cUnit, defV, dalvikRegId);
 }
 
 /*
@@ -1111,11 +1113,12 @@
     if (bb->dataFlowInfo == NULL) return false;
 
     useV = bb->dataFlowInfo->useV =
-        oatAllocBitVector(cUnit->numDalvikRegisters, false, kBitMapUse);
+        oatAllocBitVector(cUnit, cUnit->numDalvikRegisters, false, kBitMapUse);
     defV = bb->dataFlowInfo->defV =
-        oatAllocBitVector(cUnit->numDalvikRegisters, false, kBitMapDef);
+        oatAllocBitVector(cUnit, cUnit->numDalvikRegisters, false, kBitMapDef);
     liveInV = bb->dataFlowInfo->liveInV =
-        oatAllocBitVector(cUnit->numDalvikRegisters, false, kBitMapLiveIn);
+        oatAllocBitVector(cUnit, cUnit->numDalvikRegisters, false,
+                          kBitMapLiveIn);
 
     for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
         int dfAttributes =
@@ -1124,28 +1127,28 @@
 
         if (dfAttributes & DF_HAS_USES) {
             if (dfAttributes & DF_UA) {
-                handleLiveInUse(useV, defV, liveInV, dInsn->vA);
+                handleLiveInUse(cUnit, useV, defV, liveInV, dInsn->vA);
             } else if (dfAttributes & DF_UA_WIDE) {
-                handleLiveInUse(useV, defV, liveInV, dInsn->vA);
-                handleLiveInUse(useV, defV, liveInV, dInsn->vA+1);
+                handleLiveInUse(cUnit, useV, defV, liveInV, dInsn->vA);
+                handleLiveInUse(cUnit, useV, defV, liveInV, dInsn->vA+1);
             }
             if (dfAttributes & DF_UB) {
-                handleLiveInUse(useV, defV, liveInV, dInsn->vB);
+                handleLiveInUse(cUnit, useV, defV, liveInV, dInsn->vB);
             } else if (dfAttributes & DF_UB_WIDE) {
-                handleLiveInUse(useV, defV, liveInV, dInsn->vB);
-                handleLiveInUse(useV, defV, liveInV, dInsn->vB+1);
+                handleLiveInUse(cUnit, useV, defV, liveInV, dInsn->vB);
+                handleLiveInUse(cUnit, useV, defV, liveInV, dInsn->vB+1);
             }
             if (dfAttributes & DF_UC) {
-                handleLiveInUse(useV, defV, liveInV, dInsn->vC);
+                handleLiveInUse(cUnit, useV, defV, liveInV, dInsn->vC);
             } else if (dfAttributes & DF_UC_WIDE) {
-                handleLiveInUse(useV, defV, liveInV, dInsn->vC);
-                handleLiveInUse(useV, defV, liveInV, dInsn->vC+1);
+                handleLiveInUse(cUnit, useV, defV, liveInV, dInsn->vC);
+                handleLiveInUse(cUnit, useV, defV, liveInV, dInsn->vC+1);
             }
         }
         if (dfAttributes & DF_HAS_DEFS) {
-            handleDef(defV, dInsn->vA);
+            handleDef(cUnit, defV, dInsn->vA);
             if (dfAttributes & DF_DA_WIDE) {
-                handleDef(defV, dInsn->vA+1);
+                handleDef(cUnit, defV, dInsn->vA+1);
             }
         }
     }
@@ -1173,7 +1176,7 @@
     cUnit->dalvikToSSAMap[dalvikReg] = newD2SMapping;
 
     int newS2DMapping = ENCODE_REG_SUB(dalvikReg, dalvikSub);
-    oatInsertGrowableList(cUnit->ssaToDalvikMap, newS2DMapping);
+    oatInsertGrowableList(cUnit, cUnit->ssaToDalvikMap, newS2DMapping);
 
     defs[regIndex] = ssaReg;
 }
@@ -1186,10 +1189,10 @@
     int i;
 
     mir->ssaRep->numUses = numUses;
-    mir->ssaRep->uses = (int *)oatNew(sizeof(int) * numUses, true,
+    mir->ssaRep->uses = (int *)oatNew(cUnit, sizeof(int) * numUses, true,
                                       kAllocDFInfo);
     // NOTE: will be filled in during type & size inference pass
-    mir->ssaRep->fpUse = (bool *)oatNew(sizeof(bool) * numUses, true,
+    mir->ssaRep->fpUse = (bool *)oatNew(cUnit, sizeof(bool) * numUses, true,
                                         kAllocDFInfo);
 
     for (i = 0; i < numUses; i++) {
@@ -1205,10 +1208,10 @@
     int i;
 
     mir->ssaRep->numUses = numUses;
-    mir->ssaRep->uses = (int *)oatNew(sizeof(int) * numUses, true,
+    mir->ssaRep->uses = (int *)oatNew(cUnit, sizeof(int) * numUses, true,
                                       kAllocDFInfo);
     // NOTE: will be filled in during type & size inference pass
-    mir->ssaRep->fpUse = (bool *)oatNew(sizeof(bool) * numUses, true,
+    mir->ssaRep->fpUse = (bool *)oatNew(cUnit, sizeof(bool) * numUses, true,
                                         kAllocDFInfo);
 
     for (i = 0; i < numUses; i++) {
@@ -1225,7 +1228,7 @@
 
     for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
         mir->ssaRep = (struct SSARepresentation *)
-            oatNew(sizeof(SSARepresentation), true, kAllocDFInfo);
+            oatNew(cUnit, sizeof(SSARepresentation), true, kAllocDFInfo);
 
         int dfAttributes =
             oatDataFlowAttributes[mir->dalvikInsn.opcode];
@@ -1275,9 +1278,9 @@
 
         if (numUses) {
             mir->ssaRep->numUses = numUses;
-            mir->ssaRep->uses = (int *)oatNew(sizeof(int) * numUses,
+            mir->ssaRep->uses = (int *)oatNew(cUnit, sizeof(int) * numUses,
                                               false, kAllocDFInfo);
-            mir->ssaRep->fpUse = (bool *)oatNew(sizeof(bool) * numUses,
+            mir->ssaRep->fpUse = (bool *)oatNew(cUnit, sizeof(bool) * numUses,
                                                 false, kAllocDFInfo);
         }
 
@@ -1292,9 +1295,9 @@
 
         if (numDefs) {
             mir->ssaRep->numDefs = numDefs;
-            mir->ssaRep->defs = (int *)oatNew(sizeof(int) * numDefs,
+            mir->ssaRep->defs = (int *)oatNew(cUnit, sizeof(int) * numDefs,
                                               false, kAllocDFInfo);
-            mir->ssaRep->fpDef = (bool *)oatNew(sizeof(bool) * numDefs,
+            mir->ssaRep->fpDef = (bool *)oatNew(cUnit, sizeof(bool) * numDefs,
                                                 false, kAllocDFInfo);
         }
 
@@ -1347,7 +1350,7 @@
          * predecessor blocks.
          */
         bb->dataFlowInfo->dalvikToSSAMap =
-            (int *)oatNew(sizeof(int) * cUnit->numDalvikRegisters, false,
+            (int *)oatNew(cUnit, sizeof(int) * cUnit->numDalvikRegisters, false,
                           kAllocDFInfo);
 
         memcpy(bb->dataFlowInfo->dalvikToSSAMap, cUnit->dalvikToSSAMap,
@@ -1359,7 +1362,7 @@
 /* Setup a constant value for opcodes thare have the DF_SETS_CONST attribute */
 STATIC void setConstant(CompilationUnit* cUnit, int ssaReg, int value)
 {
-    oatSetBit(cUnit->isConstantV, ssaReg);
+    oatSetBit(cUnit, cUnit->isConstantV, ssaReg);
     cUnit->constantValues[ssaReg] = value;
 }
 
@@ -1442,10 +1445,10 @@
     int i;
     int numDalvikReg = cUnit->numDalvikRegisters;
 
-    cUnit->ssaToDalvikMap = (GrowableList *)oatNew(sizeof(GrowableList),
+    cUnit->ssaToDalvikMap = (GrowableList *)oatNew(cUnit, sizeof(GrowableList),
                                                    false, kAllocDFInfo);
     // Create the SSAtoDalvikMap, estimating the max size
-    oatInitGrowableList(cUnit->ssaToDalvikMap,
+    oatInitGrowableList(cUnit, cUnit->ssaToDalvikMap,
                         numDalvikReg + cUnit->defCount + 128,
                         kListSSAtoDalvikMap);
     /*
@@ -1460,7 +1463,8 @@
      * into "(0 << 16) | i"
      */
     for (i = 0; i < numDalvikReg; i++) {
-        oatInsertGrowableList(cUnit->ssaToDalvikMap, ENCODE_REG_SUB(i, 0));
+        oatInsertGrowableList(cUnit, cUnit->ssaToDalvikMap,
+                              ENCODE_REG_SUB(i, 0));
     }
 
     /*
@@ -1468,10 +1472,10 @@
      * while the high 16 bit is the current subscript. The original Dalvik
      * register N is mapped to SSA register N with subscript 0.
      */
-    cUnit->dalvikToSSAMap = (int *)oatNew(sizeof(int) * numDalvikReg,
+    cUnit->dalvikToSSAMap = (int *)oatNew(cUnit, sizeof(int) * numDalvikReg,
                                           false, kAllocDFInfo);
     /* Keep track of the higest def for each dalvik reg */
-    cUnit->SSALastDefs = (int *)oatNew(sizeof(int) * numDalvikReg,
+    cUnit->SSALastDefs = (int *)oatNew(cUnit, sizeof(int) * numDalvikReg,
                                        false, kAllocDFInfo);
 
     for (i = 0; i < numDalvikReg; i++) {
@@ -1494,7 +1498,7 @@
             bb->blockType == kEntryBlock ||
             bb->blockType == kExitBlock) {
             bb->dataFlowInfo = (BasicBlockDataFlow *)
-                oatNew(sizeof(BasicBlockDataFlow),
+                oatNew(cUnit, sizeof(BasicBlockDataFlow),
                        true, kAllocDFInfo);
         }
     }
@@ -1627,7 +1631,7 @@
 {
     if (bb->dataFlowInfo == NULL) return false;
     bb->dataFlowInfo->endingNullCheckV =
-        oatAllocBitVector(cUnit->numSSARegs, false, kBitMapNullCheck);
+        oatAllocBitVector(cUnit, cUnit->numSSARegs, false, kBitMapNullCheck);
     oatClearAllBits(bb->dataFlowInfo->endingNullCheckV);
     return true;
 }
@@ -1648,7 +1652,7 @@
         if ((cUnit->access_flags & kAccStatic) == 0) {
             // If non-static method, mark "this" as non-null
             int thisReg = cUnit->numDalvikRegisters - cUnit->numIns;
-            oatSetBit(cUnit->tempSSARegisterV, thisReg);
+            oatSetBit(cUnit, cUnit->tempSSARegisterV, thisReg);
         }
     } else {
         // Starting state is intesection of all incoming arcs
@@ -1681,7 +1685,7 @@
 
         // Mark target of NEW* as non-null
         if (dfAttributes & DF_NON_NULL_DST) {
-            oatSetBit(cUnit->tempSSARegisterV, mir->ssaRep->defs[0]);
+            oatSetBit(cUnit, cUnit->tempSSARegisterV, mir->ssaRep->defs[0]);
         }
 
         // Mark non-null returns from invoke-style NEW*
@@ -1690,7 +1694,8 @@
             // Next should be an OP_MOVE_RESULT_OBJECT
             if (nextMir && nextMir->dalvikInsn.opcode == OP_MOVE_RESULT_OBJECT) {
                 // Mark as null checked
-                oatSetBit(cUnit->tempSSARegisterV, nextMir->ssaRep->defs[0]);
+                oatSetBit(cUnit, cUnit->tempSSARegisterV,
+                          nextMir->ssaRep->defs[0]);
             } else {
                 if (nextMir) {
                     LOG(WARNING) << "Unexpected opcode following new: " <<
@@ -1706,7 +1711,7 @@
                        // First non-pseudo should be OP_MOVE_RESULT_OBJECT
                        if (tmir->dalvikInsn.opcode == OP_MOVE_RESULT_OBJECT) {
                            // Mark as null checked
-                           oatSetBit(cUnit->tempSSARegisterV,
+                           oatSetBit(cUnit, cUnit->tempSSARegisterV,
                                      tmir->ssaRep->defs[0]);
                        } else {
                            LOG(WARNING) << "Unexpected op after new: " <<
@@ -1733,7 +1738,7 @@
                     mir->ssaRep->uses[i]);
             }
             if (nullChecked) {
-                oatSetBit(cUnit->tempSSARegisterV, tgtSreg);
+                oatSetBit(cUnit, cUnit->tempSSARegisterV, tgtSreg);
             }
         }
 
@@ -1746,7 +1751,7 @@
                 mir->optimizationFlags |= MIR_IGNORE_NULL_CHECK;
             } else {
                 // Mark sReg as null-checked
-                oatSetBit(cUnit->tempSSARegisterV, srcSreg);
+                oatSetBit(cUnit, cUnit->tempSSARegisterV, srcSreg);
             }
         }
     }
diff --git a/src/compiler/Dataflow.h b/src/compiler/Dataflow.h
index cd2b1cb..22a03b7 100644
--- a/src/compiler/Dataflow.h
+++ b/src/compiler/Dataflow.h
@@ -108,7 +108,7 @@
 #define DF_IS_GETTER_OR_SETTER  (DF_IS_GETTER | DF_IS_SETTER)
 #define DF_USES_FP              (DF_FP_A | DF_FP_B | DF_FP_C)
 
-extern int oatDataFlowAttributes[kMirOpLast];
+extern const int oatDataFlowAttributes[kMirOpLast];
 
 typedef struct BasicBlockDataFlow {
     ArenaBitVector* useV;
diff --git a/src/compiler/Frontend.cc b/src/compiler/Frontend.cc
index b41afc0..38d6972 100644
--- a/src/compiler/Frontend.cc
+++ b/src/compiler/Frontend.cc
@@ -49,10 +49,6 @@
      //(1 << kDebugShowMemoryUsage) |
      0;
 
-std::string compilerMethodMatch;      // Method name match to apply above flags
-
-bool compilerFlipMatch = false;       // Reverses sense of method name match
-
 STATIC inline bool contentIsInsn(const u2* codePtr) {
     u2 instr = *codePtr;
     Opcode opcode = (Opcode)(instr & 0xff);
@@ -67,8 +63,8 @@
 /*
  * Parse an instruction, return the length of the instruction
  */
-STATIC inline int parseInsn(const u2* codePtr, DecodedInstruction* decInsn,
-                            bool printMe)
+STATIC inline int parseInsn(CompilationUnit* cUnit, const u2* codePtr,
+                            DecodedInstruction* decInsn, bool printMe)
 {
     // Don't parse instruction data
     if (!contentIsInsn(codePtr)) {
@@ -80,7 +76,7 @@
 
     dexDecodeInstruction(codePtr, decInsn);
     if (printMe) {
-        char* decodedString = oatGetDalvikDisassembly(decInsn, NULL);
+        char* decodedString = oatGetDalvikDisassembly(cUnit, decInsn, NULL);
         LOG(INFO) << codePtr << ": 0x" << std::hex << (int)opcode <<
         " " << decodedString;
     }
@@ -133,7 +129,7 @@
     }
     BasicBlock *bottomBlock = oatNewBB(cUnit, kDalvikByteCode,
                                        cUnit->numBlocks++);
-    oatInsertGrowableList(&cUnit->blockList, (intptr_t) bottomBlock);
+    oatInsertGrowableList(cUnit, &cUnit->blockList, (intptr_t) bottomBlock);
 
     bottomBlock->startOffset = codeOffset;
     bottomBlock->firstMIRInsn = insn;
@@ -149,7 +145,7 @@
         origBlock->taken = NULL;
         oatDeleteGrowableList(bottomBlock->taken->predecessors,
                               (intptr_t)origBlock);
-        oatInsertGrowableList(bottomBlock->taken->predecessors,
+        oatInsertGrowableList(cUnit, bottomBlock->taken->predecessors,
                               (intptr_t)bottomBlock);
     }
 
@@ -158,11 +154,12 @@
     bottomBlock->fallThrough = origBlock->fallThrough;
     origBlock->fallThrough = bottomBlock;
     origBlock->needFallThroughBranch = true;
-    oatInsertGrowableList(bottomBlock->predecessors, (intptr_t)origBlock);
+    oatInsertGrowableList(cUnit, bottomBlock->predecessors,
+                          (intptr_t)origBlock);
     if (bottomBlock->fallThrough) {
         oatDeleteGrowableList(bottomBlock->fallThrough->predecessors,
                               (intptr_t)origBlock);
-        oatInsertGrowableList(bottomBlock->fallThrough->predecessors,
+        oatInsertGrowableList(cUnit, bottomBlock->fallThrough->predecessors,
                               (intptr_t)bottomBlock);
     }
 
@@ -180,7 +177,8 @@
             if (successorBlockInfo == NULL) break;
             BasicBlock *bb = successorBlockInfo->block;
             oatDeleteGrowableList(bb->predecessors, (intptr_t)origBlock);
-            oatInsertGrowableList(bb->predecessors, (intptr_t)bottomBlock);
+            oatInsertGrowableList(cUnit, bb->predecessors,
+                                  (intptr_t)bottomBlock);
         }
     }
 
@@ -241,7 +239,7 @@
 
     /* Create a new one */
     bb = oatNewBB(cUnit, kDalvikByteCode, cUnit->numBlocks++);
-    oatInsertGrowableList(&cUnit->blockList, (intptr_t) bb);
+    oatInsertGrowableList(cUnit, &cUnit->blockList, (intptr_t) bb);
     bb->startOffset = codeOffset;
     cUnit->blockMap.insert(std::make_pair(bb->startOffset, bb));
     return bb;
@@ -254,7 +252,7 @@
     std::string name(PrettyMethod(cUnit->method_idx, *cUnit->dex_file));
     char startOffset[80];
     sprintf(startOffset, "_%x", cUnit->entryBlock->fallThrough->startOffset);
-    char* fileName = (char*) oatNew(
+    char* fileName = (char*) oatNew(cUnit,
                         strlen(dirPrefix) +
                         name.length() +
                         strlen(".dot") + 1, true, kAllocDebugInfo);
@@ -466,7 +464,7 @@
         int startOffset = pTry->start_addr_;
         int endOffset = startOffset + pTry->insn_count_;
         for (offset = startOffset; offset < endOffset; offset++) {
-            oatSetBit(tryBlockAddr, offset);
+            oatSetBit(cUnit, tryBlockAddr, offset);
         }
     }
 
@@ -526,7 +524,7 @@
                                        /* immedPredBlockP */
                                        &curBlock);
     curBlock->taken = takenBlock;
-    oatInsertGrowableList(takenBlock->predecessors, (intptr_t)curBlock);
+    oatInsertGrowableList(cUnit, takenBlock->predecessors, (intptr_t)curBlock);
 
     /* Always terminate the current block for conditional branches */
     if (flags & kInstrCanContinue) {
@@ -550,7 +548,7 @@
                                                  /* immedPredBlockP */
                                                  &curBlock);
         curBlock->fallThrough = fallthroughBlock;
-        oatInsertGrowableList(fallthroughBlock->predecessors,
+        oatInsertGrowableList(cUnit, fallthroughBlock->predecessors,
                               (intptr_t)curBlock);
     } else if (codePtr < codeEnd) {
         /* Create a fallthrough block for real instructions (incl. OP_NOP) */
@@ -618,7 +616,7 @@
     curBlock->successorBlockList.blockListType =
         (insn->dalvikInsn.opcode == OP_PACKED_SWITCH) ?
         kPackedSwitch : kSparseSwitch;
-    oatInitGrowableList(&curBlock->successorBlockList.blocks, size,
+    oatInitGrowableList(cUnit, &curBlock->successorBlockList.blocks, size,
                         kListSuccessorBlocks);
 
     for (i = 0; i < size; i++) {
@@ -630,14 +628,15 @@
                                           /* immedPredBlockP */
                                           &curBlock);
         SuccessorBlockInfo *successorBlockInfo =
-            (SuccessorBlockInfo *) oatNew(sizeof(SuccessorBlockInfo),
-                                                  false, kAllocSuccessor);
+            (SuccessorBlockInfo *) oatNew(cUnit, sizeof(SuccessorBlockInfo),
+                                          false, kAllocSuccessor);
         successorBlockInfo->block = caseBlock;
         successorBlockInfo->key = (insn->dalvikInsn.opcode == OP_PACKED_SWITCH)?
                                   firstKey + i : keyTable[i];
-        oatInsertGrowableList(&curBlock->successorBlockList.blocks,
+        oatInsertGrowableList(cUnit, &curBlock->successorBlockList.blocks,
                               (intptr_t) successorBlockInfo);
-        oatInsertGrowableList(caseBlock->predecessors, (intptr_t)curBlock);
+        oatInsertGrowableList(cUnit, caseBlock->predecessors,
+                              (intptr_t)curBlock);
     }
 
     /* Fall-through case */
@@ -650,7 +649,8 @@
                                              /* immedPredBlockP */
                                              NULL);
     curBlock->fallThrough = fallthroughBlock;
-    oatInsertGrowableList(fallthroughBlock->predecessors, (intptr_t)curBlock);
+    oatInsertGrowableList(cUnit, fallthroughBlock->predecessors,
+                          (intptr_t)curBlock);
 }
 
 /* Process instructions with the kInstrCanThrow flag */
@@ -671,7 +671,7 @@
         }
 
         curBlock->successorBlockList.blockListType = kCatch;
-        oatInitGrowableList(&curBlock->successorBlockList.blocks, 2,
+        oatInitGrowableList(cUnit, &curBlock->successorBlockList.blocks, 2,
                             kListSuccessorBlocks);
 
         for (;iterator.HasNext(); iterator.Next()) {
@@ -680,22 +680,23 @@
                                                false /* creat */,
                                                NULL  /* immedPredBlockP */);
             catchBlock->catchEntry = true;
-            SuccessorBlockInfo *successorBlockInfo =
-                  (SuccessorBlockInfo *) oatNew(sizeof(SuccessorBlockInfo),
-                                                false, kAllocSuccessor);
+            SuccessorBlockInfo *successorBlockInfo = (SuccessorBlockInfo *)
+                  oatNew(cUnit, sizeof(SuccessorBlockInfo), false,
+                  kAllocSuccessor);
             successorBlockInfo->block = catchBlock;
             successorBlockInfo->key = iterator.GetHandlerTypeIndex();
-            oatInsertGrowableList(&curBlock->successorBlockList.blocks,
+            oatInsertGrowableList(cUnit, &curBlock->successorBlockList.blocks,
                                   (intptr_t) successorBlockInfo);
-            oatInsertGrowableList(catchBlock->predecessors, (intptr_t)curBlock);
+            oatInsertGrowableList(cUnit, catchBlock->predecessors,
+                                  (intptr_t)curBlock);
         }
     } else {
         BasicBlock *ehBlock = oatNewBB(cUnit, kExceptionHandling,
                                        cUnit->numBlocks++);
         curBlock->taken = ehBlock;
-        oatInsertGrowableList(&cUnit->blockList, (intptr_t) ehBlock);
+        oatInsertGrowableList(cUnit, &cUnit->blockList, (intptr_t) ehBlock);
         ehBlock->startOffset = curOffset;
-        oatInsertGrowableList(ehBlock->predecessors, (intptr_t)curBlock);
+        oatInsertGrowableList(cUnit, ehBlock->predecessors, (intptr_t)curBlock);
     }
 
     /*
@@ -724,7 +725,7 @@
              */
             if (insn->dalvikInsn.opcode != OP_THROW) {
                 curBlock->fallThrough = fallthroughBlock;
-                oatInsertGrowableList(fallthroughBlock->predecessors,
+                oatInsertGrowableList(cUnit, fallthroughBlock->predecessors,
                                       (intptr_t)curBlock);
             }
         }
@@ -740,18 +741,17 @@
                                  const DexFile& dex_file, InstructionSet insnSet)
 {
     VLOG(compiler) << "Compiling " << PrettyMethod(method_idx, dex_file) << "...";
-    oatArenaReset();
 
     const u2* codePtr = code_item->insns_;
     const u2* codeEnd = code_item->insns_ + code_item->insns_size_in_code_units_;
     int numBlocks = 0;
     unsigned int curOffset = 0;
 
-    oatInit(compiler);
-
     ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
     UniquePtr<CompilationUnit> cUnit(new CompilationUnit);
     memset(cUnit.get(), 0, sizeof(*cUnit));
+
+    oatInit(cUnit.get(), compiler);
     cUnit->compiler = &compiler;
     cUnit->class_linker = class_linker;
     cUnit->dex_file = &dex_file;
@@ -772,9 +772,13 @@
     cUnit->blockMap.clear();
     cUnit->boundaryMap = std::map<unsigned int, LIR*>();
     cUnit->boundaryMap.clear();
-    bool useMatch = compilerMethodMatch.length() != 0;
-    bool match = useMatch && (compilerFlipMatch ^
-        (PrettyMethod(method_idx, dex_file).find(compilerMethodMatch) != std::string::npos));
+    // TODO: set these from command line
+    cUnit->compilerMethodMatch = new std::string("");
+    cUnit->compilerFlipMatch = false;
+    bool useMatch = cUnit->compilerMethodMatch->length() != 0;
+    bool match = useMatch && (cUnit->compilerFlipMatch ^
+        (PrettyMethod(method_idx, dex_file).find(*cUnit->compilerMethodMatch)
+        != std::string::npos));
     if (!useMatch || match) {
         cUnit->disableOpt = compilerOptimizerDisableFlags;
         cUnit->enableDebug = compilerDebugFlags;
@@ -785,24 +789,28 @@
     cUnit->attrs = (METHOD_IS_LEAF | METHOD_IS_THROW_FREE);
 
     /* Initialize the block list, estimate size based on insnsSize */
-    oatInitGrowableList(&cUnit->blockList, cUnit->insnsSize, kListBlockList);
+    oatInitGrowableList(cUnit.get(), &cUnit->blockList, cUnit->insnsSize,
+                        kListBlockList);
 
     /* Initialize the switchTables list */
-    oatInitGrowableList(&cUnit->switchTables, 4, kListSwitchTables);
+    oatInitGrowableList(cUnit.get(), &cUnit->switchTables, 4,
+                        kListSwitchTables);
 
     /* Intialize the fillArrayData list */
-    oatInitGrowableList(&cUnit->fillArrayData, 4, kListFillArrayData);
+    oatInitGrowableList(cUnit.get(), &cUnit->fillArrayData, 4,
+                        kListFillArrayData);
 
     /* Intialize the throwLaunchpads list, estimate size based on insnsSize */
-    oatInitGrowableList(&cUnit->throwLaunchpads, cUnit->insnsSize,
+    oatInitGrowableList(cUnit.get(), &cUnit->throwLaunchpads, cUnit->insnsSize,
                         kListThrowLaunchPads);
 
     /* Intialize the suspendLaunchpads list */
-    oatInitGrowableList(&cUnit->suspendLaunchpads, 2048,
+    oatInitGrowableList(cUnit.get(), &cUnit->suspendLaunchpads, 2048,
                         kListSuspendLaunchPads);
 
     /* Allocate the bit-vector to track the beginning of basic blocks */
-    ArenaBitVector *tryBlockAddr = oatAllocBitVector(cUnit->insnsSize,
+    ArenaBitVector *tryBlockAddr = oatAllocBitVector(cUnit.get(),
+                                                     cUnit->insnsSize,
                                                      true /* expandable */);
     cUnit->tryBlockAddr = tryBlockAddr;
 
@@ -813,17 +821,18 @@
     cUnit->entryBlock = entryBlock;
     cUnit->exitBlock = exitBlock;
 
-    oatInsertGrowableList(&cUnit->blockList, (intptr_t) entryBlock);
-    oatInsertGrowableList(&cUnit->blockList, (intptr_t) exitBlock);
+    oatInsertGrowableList(cUnit.get(), &cUnit->blockList, (intptr_t) entryBlock);
+    oatInsertGrowableList(cUnit.get(), &cUnit->blockList, (intptr_t) exitBlock);
 
     /* Current block to record parsed instructions */
     BasicBlock *curBlock = oatNewBB(cUnit.get(), kDalvikByteCode, numBlocks++);
     curBlock->startOffset = 0;
-    oatInsertGrowableList(&cUnit->blockList, (intptr_t) curBlock);
+    oatInsertGrowableList(cUnit.get(), &cUnit->blockList, (intptr_t) curBlock);
     /* Add first block to the fast lookup cache */
     cUnit->blockMap.insert(std::make_pair(curBlock->startOffset, curBlock));
     entryBlock->fallThrough = curBlock;
-    oatInsertGrowableList(curBlock->predecessors, (intptr_t)entryBlock);
+    oatInsertGrowableList(cUnit.get(), curBlock->predecessors,
+                          (intptr_t)entryBlock);
 
     /*
      * Store back the number of blocks since new blocks may be created of
@@ -836,9 +845,9 @@
 
     /* Parse all instructions and put them into containing basic blocks */
     while (codePtr < codeEnd) {
-        MIR *insn = (MIR *) oatNew(sizeof(MIR), true, kAllocMIR);
+        MIR *insn = (MIR *) oatNew(cUnit.get(), sizeof(MIR), true, kAllocMIR);
         insn->offset = curOffset;
-        int width = parseInsn(codePtr, &insn->dalvikInsn, false);
+        int width = parseInsn(cUnit.get(), codePtr, &insn->dalvikInsn, false);
         insn->width = width;
 
         /* Terminate when the data section is seen */
@@ -861,7 +870,8 @@
                                         width, flags, codePtr, codeEnd);
         } else if (flags & kInstrCanReturn) {
             curBlock->fallThrough = exitBlock;
-            oatInsertGrowableList(exitBlock->predecessors, (intptr_t)curBlock);
+            oatInsertGrowableList(cUnit.get(), exitBlock->predecessors,
+                                  (intptr_t)curBlock);
             /*
              * Terminate the current block if there are instructions
              * afterwards.
@@ -909,7 +919,7 @@
             if ((curBlock->fallThrough == NULL) &&
                 (flags & kInstrCanContinue)) {
                 curBlock->fallThrough = nextBlock;
-                oatInsertGrowableList(nextBlock->predecessors,
+                oatInsertGrowableList(cUnit.get(), nextBlock->predecessors,
                                       (intptr_t)curBlock);
             }
             curBlock = nextBlock;
@@ -1007,20 +1017,17 @@
     }
 #endif
 
+    oatArenaReset(cUnit.get());
+
     return result;
 }
 
-void oatInit(const Compiler& compiler)
+void oatInit(CompilationUnit* cUnit, const Compiler& compiler)
 {
-    static bool initialized = false;
-    if (initialized)
-        return;
-    initialized = true;
-    VLOG(compiler) << "Initializing compiler";
     if (!oatArchInit()) {
         LOG(FATAL) << "Failed to initialize oat";
     }
-    if (!oatHeapInit()) {
+    if (!oatHeapInit(cUnit)) {
         LOG(FATAL) << "Failed to initialize oat heap";
     }
 }
diff --git a/src/compiler/IntermediateRep.cc b/src/compiler/IntermediateRep.cc
index 6cb6580..1567fcc 100644
--- a/src/compiler/IntermediateRep.cc
+++ b/src/compiler/IntermediateRep.cc
@@ -22,12 +22,14 @@
 /* Allocate a new basic block */
 BasicBlock* oatNewBB(CompilationUnit* cUnit, BBType blockType, int blockId)
 {
-    BasicBlock* bb = (BasicBlock* )oatNew(sizeof(BasicBlock), true, kAllocBB);
+    BasicBlock* bb = (BasicBlock* )oatNew(cUnit, sizeof(BasicBlock), true,
+                                          kAllocBB);
     bb->blockType = blockType;
     bb->id = blockId;
-    bb->predecessors = (GrowableList*) oatNew(sizeof(GrowableList), false,
-                                              kAllocPredecessors);
-    oatInitGrowableList(bb->predecessors, (blockType == kExitBlock) ? 2048 : 2,
+    bb->predecessors = (GrowableList*) oatNew(cUnit, sizeof(GrowableList),
+                                              false, kAllocPredecessors);
+    oatInitGrowableList(cUnit, bb->predecessors,
+                        (blockType == kExitBlock) ? 2048 : 2,
                         kListPredecessors);
     return bb;
 }
diff --git a/src/compiler/Ralloc.cc b/src/compiler/Ralloc.cc
index 4529a83..b450393 100644
--- a/src/compiler/Ralloc.cc
+++ b/src/compiler/Ralloc.cc
@@ -315,7 +315,7 @@
     RegLocation* loc;
 
     /* Allocate the location map */
-    loc = (RegLocation*)oatNew(cUnit->numSSARegs * sizeof(*loc), true,
+    loc = (RegLocation*)oatNew(cUnit, cUnit->numSSARegs * sizeof(*loc), true,
                                kAllocRegAlloc);
     for (i=0; i< cUnit->numSSARegs; i++) {
         loc[i] = freshLoc;
@@ -326,8 +326,8 @@
     /* Allocation the promotion map */
     int numRegs = cUnit->numDalvikRegisters;
     cUnit->promotionMap =
-        (PromotionMap*)oatNew(numRegs * sizeof(cUnit->promotionMap[0]), true,
-                              kAllocRegAlloc);
+        (PromotionMap*)oatNew(cUnit, numRegs * sizeof(cUnit->promotionMap[0]),
+                              true, kAllocRegAlloc);
 
     /* Add types of incoming arguments based on signature */
     int numIns = cUnit->numIns;
diff --git a/src/compiler/SSATransformation.cc b/src/compiler/SSATransformation.cc
index 3e1728f..99de0a7 100644
--- a/src/compiler/SSATransformation.cc
+++ b/src/compiler/SSATransformation.cc
@@ -27,7 +27,7 @@
     block->visited = true;
 
     /* Enqueue the preOrder block id */
-    oatInsertGrowableList(&cUnit->dfsOrder, block->id);
+    oatInsertGrowableList(cUnit, &cUnit->dfsOrder, block->id);
 
     if (block->fallThrough) recordDFSOrders(cUnit, block->fallThrough);
     if (block->taken) recordDFSOrders(cUnit, block->taken);
@@ -46,7 +46,7 @@
 
     /* Record postorder in basic block and enqueue normal id in dfsPostOrder */
     block->dfsId = cUnit->dfsPostOrder.numUsed;
-    oatInsertGrowableList(&cUnit->dfsPostOrder, block->id);
+    oatInsertGrowableList(cUnit, &cUnit->dfsPostOrder, block->id);
     return;
 }
 
@@ -55,7 +55,8 @@
 {
     /* Initialize or reset the DFS preOrder list */
     if (cUnit->dfsOrder.elemList == NULL) {
-        oatInitGrowableList(&cUnit->dfsOrder, cUnit->numBlocks, kListDfsOrder);
+        oatInitGrowableList(cUnit, &cUnit->dfsOrder, cUnit->numBlocks,
+                            kListDfsOrder);
     } else {
         /* Just reset the used length on the counter */
         cUnit->dfsOrder.numUsed = 0;
@@ -63,7 +64,7 @@
 
     /* Initialize or reset the DFS postOrder list */
     if (cUnit->dfsPostOrder.elemList == NULL) {
-        oatInitGrowableList(&cUnit->dfsPostOrder, cUnit->numBlocks,
+        oatInitGrowableList(cUnit, &cUnit->dfsPostOrder, cUnit->numBlocks,
                             kListDfsPostOrder);
     } else {
         /* Just reset the used length on the counter */
@@ -93,7 +94,7 @@
         int idx = oatBitVectorIteratorNext(&iterator);
         if (idx == -1) break;
         /* Block bb defines register idx */
-        oatSetBit(cUnit->defBlockMatrix[idx], bb->id);
+        oatSetBit(cUnit, cUnit->defBlockMatrix[idx], bb->id);
     }
     return true;
 }
@@ -103,14 +104,14 @@
     int numRegisters = cUnit->numDalvikRegisters;
     /* Allocate numDalvikRegisters bit vector pointers */
     cUnit->defBlockMatrix = (ArenaBitVector **)
-        oatNew(sizeof(ArenaBitVector *) * numRegisters, true,
+        oatNew(cUnit, sizeof(ArenaBitVector *) * numRegisters, true,
                kAllocDFInfo);
     int i;
 
     /* Initialize numRegister vectors with numBlocks bits each */
     for (i = 0; i < numRegisters; i++) {
-        cUnit->defBlockMatrix[i] = oatAllocBitVector(cUnit->numBlocks, false,
-                                                     kBitMapBMatrix);
+        cUnit->defBlockMatrix[i] = oatAllocBitVector(cUnit, cUnit->numBlocks,
+                                                     false, kBitMapBMatrix);
     }
     oatDataFlowAnalysisDispatcher(cUnit, oatFindLocalLiveIn,
                                           kAllNodes,
@@ -126,7 +127,7 @@
     int numRegs = cUnit->numDalvikRegisters;
     int inReg = numRegs - cUnit->numIns;
     for (; inReg < numRegs; inReg++) {
-        oatSetBit(cUnit->defBlockMatrix[inReg], cUnit->entryBlock->id);
+        oatSetBit(cUnit, cUnit->defBlockMatrix[inReg], cUnit->entryBlock->id);
     }
 }
 
@@ -148,7 +149,7 @@
     }
 
     /* Enter the current block id */
-    oatInsertGrowableList(&cUnit->domPostOrderTraversal, bb->id);
+    oatInsertGrowableList(cUnit, &cUnit->domPostOrderTraversal, bb->id);
 
     /* hacky loop detection */
     if (bb->taken && oatIsBitSet(bb->dominators, bb->taken->id)) {
@@ -156,7 +157,7 @@
     }
 }
 
-STATIC void checkForDominanceFrontier(BasicBlock* domBB,
+STATIC void checkForDominanceFrontier(CompilationUnit* cUnit, BasicBlock* domBB,
                                       const BasicBlock* succBB)
 {
     /*
@@ -166,7 +167,7 @@
     if (succBB->iDom != domBB &&
         succBB->blockType == kDalvikByteCode &&
         succBB->hidden == false) {
-        oatSetBit(domBB->domFrontier, succBB->id);
+        oatSetBit(cUnit, domBB->domFrontier, succBB->id);
     }
 }
 
@@ -177,10 +178,10 @@
 
     /* Calculate DF_local */
     if (bb->taken) {
-        checkForDominanceFrontier(bb, bb->taken);
+        checkForDominanceFrontier(cUnit, bb, bb->taken);
     }
     if (bb->fallThrough) {
-        checkForDominanceFrontier(bb, bb->fallThrough);
+        checkForDominanceFrontier(cUnit, bb, bb->fallThrough);
     }
     if (bb->successorBlockList.blockListType != kNotUsed) {
         GrowableListIterator iterator;
@@ -191,7 +192,7 @@
                 (SuccessorBlockInfo *) oatGrowableListIteratorNext(&iterator);
             if (successorBlockInfo == NULL) break;
             BasicBlock* succBB = successorBlockInfo->block;
-            checkForDominanceFrontier(bb, succBB);
+            checkForDominanceFrontier(cUnit, bb, succBB);
         }
     }
 
@@ -212,7 +213,7 @@
             if (dfUpIdx == -1) break;
             BasicBlock* dfUpBlock = (BasicBlock* )
                 oatGrowableListGetElement(blockList, dfUpIdx);
-            checkForDominanceFrontier(bb, dfUpBlock);
+            checkForDominanceFrontier(cUnit, bb, dfUpBlock);
         }
     }
 
@@ -225,13 +226,13 @@
     int numTotalBlocks = cUnit->blockList.numUsed;
 
     if (bb->dominators == NULL ) {
-        bb->dominators = oatAllocBitVector(numTotalBlocks,
+        bb->dominators = oatAllocBitVector(cUnit, numTotalBlocks,
                                            false /* expandable */,
                                            kBitMapDominators);
-        bb->iDominated = oatAllocBitVector(numTotalBlocks,
+        bb->iDominated = oatAllocBitVector(cUnit, numTotalBlocks,
                                            false /* expandable */,
                                            kBitMapIDominated);
-        bb->domFrontier = oatAllocBitVector(numTotalBlocks,
+        bb->domFrontier = oatAllocBitVector(cUnit, numTotalBlocks,
                                             false /* expandable */,
                                             kBitMapDomFrontier);
     } else {
@@ -275,7 +276,7 @@
             oatIntersectBitVectors(tempBlockV, tempBlockV, predBB->dominators);
         }
     }
-    oatSetBit(tempBlockV, bb->id);
+    oatSetBit(cUnit, tempBlockV, bb->id);
     if (oatCompareBitVectors(tempBlockV, bb->dominators)) {
         oatCopyBitVector(bb->dominators, tempBlockV);
         return true;
@@ -326,7 +327,7 @@
         bb->iDom = iDom;
     }
     /* Add bb to the iDominated set of the immediate dominator block */
-    oatSetBit(iDom->iDominated, bb->id);
+    oatSetBit(cUnit, iDom->iDominated, bb->id);
     return true;
 }
 
@@ -403,7 +404,7 @@
     } else {
         oatCopyBitVector(bb->dominators, bb->iDom->dominators);
     }
-    oatSetBit(bb->dominators, bb->id);
+    oatSetBit(cUnit, bb->dominators, bb->id);
     return false;
 }
 
@@ -420,7 +421,7 @@
         }
         bb->iDom = iDom;
         /* Add bb to the iDominated set of the immediate dominator block */
-        oatSetBit(iDom->iDominated, bb->id);
+        oatSetBit(cUnit, iDom->iDominated, bb->id);
     }
     return false;
 }
@@ -438,8 +439,8 @@
 
     /* Initalize & Clear iDomList */
     if (cUnit->iDomList == NULL) {
-        cUnit->iDomList = (int*)oatNew(sizeof(int) * numReachableBlocks, false,
-                                       kAllocDFInfo);
+        cUnit->iDomList = (int*)oatNew(cUnit, sizeof(int) * numReachableBlocks,
+                                       false, kAllocDFInfo);
     }
     for (int i = 0; i < numReachableBlocks; i++) {
         cUnit->iDomList[i] = NOTVISITED;
@@ -456,10 +457,10 @@
 
     /* Set the dominator for the root node */
     oatClearAllBits(cUnit->entryBlock->dominators);
-    oatSetBit(cUnit->entryBlock->dominators, cUnit->entryBlock->id);
+    oatSetBit(cUnit, cUnit->entryBlock->dominators, cUnit->entryBlock->id);
 
     if (cUnit->tempBlockV == NULL) {
-        cUnit->tempBlockV = oatAllocBitVector(numTotalBlocks,
+        cUnit->tempBlockV = oatAllocBitVector(cUnit, numTotalBlocks,
                                               false /* expandable */,
                                               kBitMapTmpBlockV);
     } else {
@@ -492,8 +493,8 @@
      * iDominated sets.
      */
     if (cUnit->domPostOrderTraversal.elemList == NULL) {
-        oatInitGrowableList(&cUnit->domPostOrderTraversal, numReachableBlocks,
-                            kListDomPostOrderTraversal);
+        oatInitGrowableList(cUnit, &cUnit->domPostOrderTraversal,
+                            numReachableBlocks, kListDomPostOrderTraversal);
     } else {
         cUnit->domPostOrderTraversal.numUsed = 0;
     }
@@ -576,14 +577,14 @@
     int dalvikReg;
     const GrowableList* blockList = &cUnit->blockList;
     ArenaBitVector* phiBlocks =
-        oatAllocBitVector(cUnit->numBlocks, false, kBitMapPhi);
+        oatAllocBitVector(cUnit, cUnit->numBlocks, false, kBitMapPhi);
     ArenaBitVector* tmpBlocks =
-        oatAllocBitVector(cUnit->numBlocks, false, kBitMapTmpBlocks);
+        oatAllocBitVector(cUnit, cUnit->numBlocks, false, kBitMapTmpBlocks);
     ArenaBitVector* inputBlocks =
-        oatAllocBitVector(cUnit->numBlocks, false, kBitMapInputBlocks);
+        oatAllocBitVector(cUnit, cUnit->numBlocks, false, kBitMapInputBlocks);
 
     cUnit->tempDalvikRegisterV =
-        oatAllocBitVector(cUnit->numDalvikRegisters, false,
+        oatAllocBitVector(cUnit, cUnit->numDalvikRegisters, false,
                           kBitMapRegisterV);
 
     oatDataFlowAnalysisDispatcher(cUnit, computeBlockLiveIns,
@@ -642,7 +643,7 @@
                 (BasicBlock* ) oatGrowableListGetElement(blockList, idx);
             /* Variable will be clobbered before being used - no need for phi */
             if (!oatIsBitSet(phiBB->dataFlowInfo->liveInV, dalvikReg)) continue;
-            MIR *phi = (MIR *) oatNew(sizeof(MIR), true, kAllocDFInfo);
+            MIR *phi = (MIR *) oatNew(cUnit, sizeof(MIR), true, kAllocDFInfo);
             phi->dalvikInsn.opcode = (Opcode)kMirOpPhi;
             phi->dalvikInsn.vA = dalvikReg;
             phi->offset = phiBB->startOffset;
@@ -683,16 +684,16 @@
             int encodedSSAValue =
                 predBB->dataFlowInfo->dalvikToSSAMap[dalvikReg];
             int ssaReg = DECODE_REG(encodedSSAValue);
-            oatSetBit(ssaRegV, ssaReg);
+            oatSetBit(cUnit, ssaRegV, ssaReg);
         }
 
         /* Count the number of SSA registers for a Dalvik register */
         int numUses = oatCountSetBits(ssaRegV);
         mir->ssaRep->numUses = numUses;
         mir->ssaRep->uses =
-            (int *) oatNew(sizeof(int) * numUses, false, kAllocDFInfo);
+            (int *) oatNew(cUnit, sizeof(int) * numUses, false, kAllocDFInfo);
         mir->ssaRep->fpUse =
-            (bool *) oatNew(sizeof(bool) * numUses, true, kAllocDFInfo);
+            (bool *) oatNew(cUnit, sizeof(bool) * numUses, true, kAllocDFInfo);
 
         ArenaBitVectorIterator phiIterator;
 
@@ -721,7 +722,8 @@
     int mapSize = sizeof(int) * cUnit->numDalvikRegisters;
 
     /* Save SSA map snapshot */
-    int* savedSSAMap = (int*)oatNew(mapSize, false, kAllocDalvikToSSAMap);
+    int* savedSSAMap = (int*)oatNew(cUnit, mapSize, false,
+                                    kAllocDalvikToSSAMap);
     memcpy(savedSSAMap, cUnit->dalvikToSSAMap, mapSize);
 
     if (block->fallThrough) {
@@ -785,8 +787,8 @@
          * Shared temp bit vector used by each block to count the number of defs
          * from all the predecessor blocks.
          */
-        cUnit->tempSSARegisterV = oatAllocBitVector(cUnit->numSSARegs, false,
-                                                    kBitMapTempSSARegisterV);
+        cUnit->tempSSARegisterV = oatAllocBitVector(cUnit, cUnit->numSSARegs,
+             false, kBitMapTempSSARegisterV);
 
         /* Insert phi-operands with latest SSA names from predecessor blocks */
         oatDataFlowAnalysisDispatcher(cUnit, insertPhiNodeOperands,
diff --git a/src/compiler/Utility.cc b/src/compiler/Utility.cc
index 0cdcfd3..defd647 100644
--- a/src/compiler/Utility.cc
+++ b/src/compiler/Utility.cc
@@ -19,18 +19,17 @@
 
 namespace art {
 
-static ArenaMemBlock *arenaHead, *currentArena;
-static int numArenaBlocks;
-
 #ifdef WITH_MEMSTATS
-static u4 allocStats[kNumAllocKinds];
-static int listSizes[kNumListKinds];
-static int listWasted[kNumListKinds];
-static int listGrows[kNumListKinds];
-static int listMaxElems[kNumListKinds];
-static int bitMapSizes[kNumBitMapKinds];
-static int bitMapWasted[kNumBitMapKinds];
-static int bitMapGrows[kNumBitMapKinds];
+typedef struct Memstats {
+    u4 allocStats[kNumAllocKinds];
+    int listSizes[kNumListKinds];
+    int listWasted[kNumListKinds];
+    int listGrows[kNumListKinds];
+    int listMaxElems[kNumListKinds];
+    int bitMapSizes[kNumBitMapKinds];
+    int bitMapWasted[kNumBitMapKinds];
+    int bitMapGrows[kNumBitMapKinds];
+} memstats;
 
 const char* allocNames[kNumAllocKinds] = {
     "Misc       ",
@@ -86,35 +85,42 @@
 #define kArenaBitVectorGrowth    4   /* increase by 4 u4s when limit hit */
 
 /* Allocate the initial memory block for arena-based allocation */
-bool oatHeapInit(void)
+bool oatHeapInit(CompilationUnit* cUnit)
 {
-    DCHECK(arenaHead == NULL);
-    arenaHead =
+    DCHECK(cUnit->arenaHead == NULL);
+    cUnit->arenaHead =
         (ArenaMemBlock *) malloc(sizeof(ArenaMemBlock) + ARENA_DEFAULT_SIZE);
-    if (arenaHead == NULL) {
+    if (cUnit->arenaHead == NULL) {
         LOG(FATAL) << "No memory left to create compiler heap memory";
     }
-    arenaHead->blockSize = ARENA_DEFAULT_SIZE;
-    currentArena = arenaHead;
-    currentArena->bytesAllocated = 0;
-    currentArena->next = NULL;
-    numArenaBlocks = 1;
+    cUnit->arenaHead->blockSize = ARENA_DEFAULT_SIZE;
+    cUnit->currentArena = cUnit->arenaHead;
+    cUnit->currentArena->bytesAllocated = 0;
+    cUnit->currentArena->next = NULL;
+    cUnit->numArenaBlocks = 1;
+#ifdef WITH_MEMSTATS
+    cUnit->mstats = (Memstats*) oatNew(cUnit, sizeof(Memstats), true,
+                     kAllocDebugInfo);
+#endif
     return true;
 }
 
 /* Arena-based malloc for compilation tasks */
-void* oatNew(size_t size, bool zero, oatAllocKind kind)
+void* oatNew(CompilationUnit* cUnit, size_t size, bool zero, oatAllocKind kind)
 {
     size = (size + 3) & ~3;
 #ifdef WITH_MEMSTATS
-    allocStats[kind] += size;
+    if (cUnit->mstats != NULL) {
+        cUnit->mstats->allocStats[kind] += size;
+    }
 #endif
 retry:
     /* Normal case - space is available in the current page */
-    if (size + currentArena->bytesAllocated <= currentArena->blockSize) {
+    if (size + cUnit->currentArena->bytesAllocated <=
+        cUnit->currentArena->blockSize) {
         void *ptr;
-        ptr = &currentArena->ptr[currentArena->bytesAllocated];
-        currentArena->bytesAllocated += size;
+        ptr = &cUnit->currentArena->ptr[cUnit->currentArena->bytesAllocated];
+        cUnit->currentArena->bytesAllocated += size;
         if (zero) {
             memset(ptr, 0, size);
         }
@@ -124,9 +130,9 @@
          * See if there are previously allocated arena blocks before the last
          * reset
          */
-        if (currentArena->next) {
-            currentArena = currentArena->next;
-            currentArena->bytesAllocated = 0;
+        if (cUnit->currentArena->next) {
+            cUnit->currentArena = cUnit->currentArena->next;
+            cUnit->currentArena->bytesAllocated = 0;
             goto retry;
         }
 
@@ -141,54 +147,48 @@
         newArena->blockSize = blockSize;
         newArena->bytesAllocated = 0;
         newArena->next = NULL;
-        currentArena->next = newArena;
-        currentArena = newArena;
-        numArenaBlocks++;
-        if (numArenaBlocks > 20000) {
-            LOG(INFO) << "Total arena pages: " << numArenaBlocks;
+        cUnit->currentArena->next = newArena;
+        cUnit->currentArena = newArena;
+        cUnit->numArenaBlocks++;
+        if (cUnit->numArenaBlocks > 20000) {
+            LOG(INFO) << "Total arena pages: " << cUnit->numArenaBlocks;
         }
         goto retry;
     }
 }
 
 /* Reclaim all the arena blocks allocated so far */
-void oatArenaReset(void)
+void oatArenaReset(CompilationUnit* cUnit)
 {
-#ifdef WITH_MEMSTATS
-    memset(&allocStats[0], 0, sizeof(allocStats));
-    memset(&listSizes[0], 0, sizeof(listSizes));
-    memset(&listWasted[0], 0, sizeof(listWasted));
-    memset(&listGrows[0], 0, sizeof(listGrows));
-    memset(&listMaxElems[0], 0, sizeof(listMaxElems));
-    memset(&bitMapSizes[0], 0, sizeof(bitMapSizes));
-    memset(&bitMapWasted[0], 0, sizeof(bitMapWasted));
-    memset(&bitMapGrows[0], 0, sizeof(bitMapGrows));
-#endif
-    currentArena = arenaHead;
-    if (currentArena) {
-        currentArena->bytesAllocated = 0;
+    ArenaMemBlock* head = cUnit->arenaHead;
+    while (head != NULL) {
+        ArenaMemBlock* p = head;
+        head = head->next;
+        free(p);
     }
+    cUnit->arenaHead = NULL;
+    cUnit->currentArena = NULL;
 }
 
 /* Growable List initialization */
-void oatInitGrowableList(GrowableList* gList, size_t initLength,
-                         oatListKind kind)
+void oatInitGrowableList(CompilationUnit* cUnit, GrowableList* gList,
+                         size_t initLength, oatListKind kind)
 {
     gList->numAllocated = initLength;
     gList->numUsed = 0;
-    gList->elemList = (intptr_t *) oatNew(sizeof(intptr_t) * initLength,
-                                                  true, kAllocGrowableList);
+    gList->elemList = (intptr_t *) oatNew(cUnit, sizeof(intptr_t) * initLength,
+                                          true, kAllocGrowableList);
 #ifdef WITH_MEMSTATS
-    listSizes[kind] += sizeof(intptr_t) * initLength;
+    cUnit->mstats->listSizes[kind] += sizeof(intptr_t) * initLength;
     gList->kind = kind;
-    if ((int)initLength > listMaxElems[kind]) {
-        listMaxElems[kind] = initLength;
+    if ((int)initLength > cUnit->mstats->listMaxElems[kind]) {
+        cUnit->mstats->listMaxElems[kind] = initLength;
     }
 #endif
 }
 
 /* Expand the capacity of a growable list */
-STATIC void expandGrowableList(GrowableList* gList)
+STATIC void expandGrowableList(CompilationUnit* cUnit, GrowableList* gList)
 {
     int newLength = gList->numAllocated;
     if (newLength < 128) {
@@ -197,15 +197,16 @@
         newLength += 128;
     }
     intptr_t *newArray =
-        (intptr_t *) oatNew(sizeof(intptr_t) * newLength, true,
+        (intptr_t *) oatNew(cUnit, sizeof(intptr_t) * newLength, true,
                             kAllocGrowableList);
     memcpy(newArray, gList->elemList, sizeof(intptr_t) * gList->numAllocated);
 #ifdef WITH_MEMSTATS
-    listSizes[gList->kind] += sizeof(intptr_t) * newLength;
-    listWasted[gList->kind] += sizeof(intptr_t) * gList->numAllocated;
-    listGrows[gList->kind]++;
-    if (newLength > listMaxElems[gList->kind]) {
-        listMaxElems[gList->kind] = newLength;
+    cUnit->mstats->listSizes[gList->kind] += sizeof(intptr_t) * newLength;
+    cUnit->mstats->listWasted[gList->kind] +=
+        sizeof(intptr_t) * gList->numAllocated;
+    cUnit->mstats->listGrows[gList->kind]++;
+    if (newLength > cUnit->mstats->listMaxElems[gList->kind]) {
+        cUnit->mstats->listMaxElems[gList->kind] = newLength;
     }
 #endif
     gList->numAllocated = newLength;
@@ -213,11 +214,12 @@
 }
 
 /* Insert a new element into the growable list */
-void oatInsertGrowableList(GrowableList* gList, intptr_t elem)
+void oatInsertGrowableList(CompilationUnit* cUnit, GrowableList* gList,
+                           intptr_t elem)
 {
     DCHECK_NE(gList->numAllocated, 0U);
     if (gList->numUsed == gList->numAllocated) {
-        expandGrowableList(gList);
+        expandGrowableList(cUnit, gList);
     }
     gList->elemList[gList->numUsed++] = elem;
 }
@@ -265,7 +267,7 @@
 {
     u4 total = 0;
     for (int i = 0; i < kNumAllocKinds; i++) {
-        total += allocStats[i];
+        total += cUnit->mstats->allocStats[i];
     }
     if (total > (10 * 1024 * 1024)) {
         LOG(INFO) << "MEMUSAGE: " << total << " : "
@@ -276,22 +278,23 @@
         }
         LOG(INFO) << "===== Overall allocations";
         for (int i = 0; i < kNumAllocKinds; i++) {
-            LOG(INFO) << allocNames[i] << std::setw(10) <<allocStats[i];
+            LOG(INFO) << allocNames[i] << std::setw(10) <<
+            cUnit->mstats->allocStats[i];
         }
         LOG(INFO) << "===== GrowableList allocations";
         for (int i = 0; i < kNumListKinds; i++) {
             LOG(INFO) << listNames[i]
-                << " S:" << listSizes[i]
-                << ", W:" << listWasted[i]
-                << ", G:" << listGrows[i]
-                << ", E:" << listMaxElems[i];
+                << " S:" << cUnit->mstats->listSizes[i]
+                << ", W:" << cUnit->mstats->listWasted[i]
+                << ", G:" << cUnit->mstats->listGrows[i]
+                << ", E:" << cUnit->mstats->listMaxElems[i];
         }
         LOG(INFO) << "===== GrowableBitMap allocations";
         for (int i = 0; i < kNumBitMapKinds; i++) {
             LOG(INFO) << bitMapNames[i]
-                << " S:" << bitMapSizes[i]
-                << ", W:" << bitMapWasted[i]
-                << ", G:" << bitMapGrows[i];
+                << " S:" << cUnit->mstats->bitMapSizes[i]
+                << ", W:" << cUnit->mstats->bitMapWasted[i]
+                << ", G:" << cUnit->mstats->bitMapGrows[i];
         }
     }
 }
@@ -361,7 +364,8 @@
  *
  * NOTE: memory is allocated from the compiler arena.
  */
-ArenaBitVector* oatAllocBitVector(unsigned int startBits, bool expandable,
+ArenaBitVector* oatAllocBitVector(CompilationUnit* cUnit,
+                                  unsigned int startBits, bool expandable,
                                   oatBitMapKind kind)
 {
     ArenaBitVector* bv;
@@ -369,17 +373,18 @@
 
     DCHECK_EQ(sizeof(bv->storage[0]), 4U);        /* assuming 32-bit units */
 
-    bv = (ArenaBitVector*) oatNew(sizeof(ArenaBitVector), false,
+    bv = (ArenaBitVector*) oatNew(cUnit, sizeof(ArenaBitVector), false,
                                   kAllocGrowableBitMap);
 
     count = (startBits + 31) >> 5;
 
     bv->storageSize = count;
     bv->expandable = expandable;
-    bv->storage = (u4*) oatNew(count * sizeof(u4), true, kAllocGrowableBitMap);
+    bv->storage = (u4*) oatNew(cUnit, count * sizeof(u4), true,
+                               kAllocGrowableBitMap);
 #ifdef WITH_MEMSTATS
     bv->kind = kind;
-    bitMapSizes[kind] += count * sizeof(u4);
+    cUnit->mstats->bitMapSizes[kind] += count * sizeof(u4);
 #endif
     return bv;
 }
@@ -412,7 +417,7 @@
  *
  * NOTE: memory is allocated from the compiler arena.
  */
-bool oatSetBit(ArenaBitVector* pBits, unsigned int num)
+bool oatSetBit(CompilationUnit* cUnit, ArenaBitVector* pBits, unsigned int num)
 {
     if (num >= pBits->storageSize * sizeof(u4) * 8) {
         if (!pBits->expandable) {
@@ -422,15 +427,16 @@
         /* Round up to word boundaries for "num+1" bits */
         unsigned int newSize = (num + 1 + 31) >> 5;
         DCHECK_GT(newSize, pBits->storageSize);
-        u4 *newStorage = (u4*)oatNew(newSize * sizeof(u4), false,
+        u4 *newStorage = (u4*)oatNew(cUnit, newSize * sizeof(u4), false,
                                      kAllocGrowableBitMap);
         memcpy(newStorage, pBits->storage, pBits->storageSize * sizeof(u4));
         memset(&newStorage[pBits->storageSize], 0,
                (newSize - pBits->storageSize) * sizeof(u4));
 #ifdef WITH_MEMSTATS
-        bitMapWasted[pBits->kind] += pBits->storageSize * sizeof(u4);
-        bitMapSizes[pBits->kind] += newSize * sizeof(u4);
-        bitMapGrows[pBits->kind]++;
+        cUnit->mstats->bitMapWasted[pBits->kind] +=
+            pBits->storageSize * sizeof(u4);
+        cUnit->mstats->bitMapSizes[pBits->kind] += newSize * sizeof(u4);
+        cUnit->mstats->bitMapGrows[pBits->kind]++;
 #endif
         pBits->storage = newStorage;
         pBits->storageSize = newSize;
diff --git a/src/compiler/codegen/arm/ArchFactory.cc b/src/compiler/codegen/arm/ArchFactory.cc
index 484a22d..d700e48 100644
--- a/src/compiler/codegen/arm/ArchFactory.cc
+++ b/src/compiler/codegen/arm/ArchFactory.cc
@@ -56,20 +56,20 @@
 STATIC ArmLIR* genCheck(CompilationUnit* cUnit, ArmConditionCode cCode,
                         MIR* mir, ArmThrowKind kind)
 {
-    ArmLIR* tgt = (ArmLIR*)oatNew(sizeof(ArmLIR), true, kAllocLIR);
+    ArmLIR* tgt = (ArmLIR*)oatNew(cUnit, sizeof(ArmLIR), true, kAllocLIR);
     tgt->opcode = kArmPseudoThrowTarget;
     tgt->operands[0] = kind;
     tgt->operands[1] = mir ? mir->offset : 0;
     ArmLIR* branch = genConditionalBranch(cUnit, cCode, tgt);
     // Remember branch target - will process later
-    oatInsertGrowableList(&cUnit->throwLaunchpads, (intptr_t)tgt);
+    oatInsertGrowableList(cUnit, &cUnit->throwLaunchpads, (intptr_t)tgt);
     return branch;
 }
 
 STATIC ArmLIR* genImmedCheck(CompilationUnit* cUnit, ArmConditionCode cCode,
                              int reg, int immVal, MIR* mir, ArmThrowKind kind)
 {
-    ArmLIR* tgt = (ArmLIR*)oatNew(sizeof(ArmLIR), true, kAllocLIR);
+    ArmLIR* tgt = (ArmLIR*)oatNew(cUnit, sizeof(ArmLIR), true, kAllocLIR);
     tgt->opcode = kArmPseudoThrowTarget;
     tgt->operands[0] = kind;
     tgt->operands[1] = mir->offset;
@@ -81,7 +81,7 @@
         branch->generic.target = (LIR*)tgt;
     }
     // Remember branch target - will process later
-    oatInsertGrowableList(&cUnit->throwLaunchpads, (intptr_t)tgt);
+    oatInsertGrowableList(cUnit, &cUnit->throwLaunchpads, (intptr_t)tgt);
     return branch;
 }
 
@@ -100,7 +100,7 @@
 STATIC TGT_LIR* genRegRegCheck(CompilationUnit* cUnit, ArmConditionCode cCode,
                                int reg1, int reg2, MIR* mir, ArmThrowKind kind)
 {
-    ArmLIR* tgt = (ArmLIR*)oatNew(sizeof(ArmLIR), true, kAllocLIR);
+    ArmLIR* tgt = (ArmLIR*)oatNew(cUnit, sizeof(ArmLIR), true, kAllocLIR);
     tgt->opcode = kArmPseudoThrowTarget;
     tgt->operands[0] = kind;
     tgt->operands[1] = mir ? mir->offset : 0;
@@ -109,7 +109,7 @@
     opRegReg(cUnit, kOpCmp, reg1, reg2);
     ArmLIR* branch = genConditionalBranch(cUnit, cCode, tgt);
     // Remember branch target - will process later
-    oatInsertGrowableList(&cUnit->throwLaunchpads, (intptr_t)tgt);
+    oatInsertGrowableList(cUnit, &cUnit->throwLaunchpads, (intptr_t)tgt);
     return branch;
 }
 
diff --git a/src/compiler/codegen/arm/ArmLIR.h b/src/compiler/codegen/arm/ArmLIR.h
index 3c5daad..bc536f9 100644
--- a/src/compiler/codegen/arm/ArmLIR.h
+++ b/src/compiler/codegen/arm/ArmLIR.h
@@ -822,7 +822,7 @@
     kMaxHoistDistance,
 } ArmTargetOptHints;
 
-extern ArmEncodingMap EncodingMap[kArmLast];
+extern const ArmEncodingMap EncodingMap[kArmLast];
 
 /*
  * Each instance of this struct holds a pseudo or real LIR instruction:
diff --git a/src/compiler/codegen/arm/ArmRallocUtil.cc b/src/compiler/codegen/arm/ArmRallocUtil.cc
index d540007..1986b0f 100644
--- a/src/compiler/codegen/arm/ArmRallocUtil.cc
+++ b/src/compiler/codegen/arm/ArmRallocUtil.cc
@@ -132,9 +132,9 @@
      * reg.
      */
     RefCounts *coreRegs = (RefCounts *)
-          oatNew(sizeof(RefCounts) * numRegs, true, kAllocRegAlloc);
+          oatNew(cUnit, sizeof(RefCounts) * numRegs, true, kAllocRegAlloc);
     RefCounts *fpRegs = (RefCounts *)
-          oatNew(sizeof(RefCounts) * numRegs, true, kAllocRegAlloc);
+          oatNew(cUnit, sizeof(RefCounts) * numRegs, true, kAllocRegAlloc);
     for (int i = 0; i < numRegs; i++) {
         coreRegs[i].sReg = fpRegs[i].sReg = i;
     }
diff --git a/src/compiler/codegen/arm/Assemble.cc b/src/compiler/codegen/arm/Assemble.cc
index f270631..2990631 100644
--- a/src/compiler/codegen/arm/Assemble.cc
+++ b/src/compiler/codegen/arm/Assemble.cc
@@ -80,7 +80,7 @@
  *  [!] escape.  To insert "!", use "!!"
  */
 /* NOTE: must be kept in sync with enum ArmOpcode from ArmLIR.h */
-ArmEncodingMap EncodingMap[kArmLast] = {
+const ArmEncodingMap EncodingMap[kArmLast] = {
     ENCODING_MAP(kArm16BitData,    0x0000,
                  kFmtBitBlt, 15, 0, kFmtUnused, -1, -1, kFmtUnused, -1, -1,
                  kFmtUnused, -1, -1, IS_UNARY_OP, "data", "0x!0h(!0d)", 1),
@@ -1131,8 +1131,8 @@
                         lir->operands[0] : rLR;
 
                     // Add new Adr to generate the address
-                    ArmLIR *newAdr =
-                        (ArmLIR *)oatNew(sizeof(ArmLIR), true, kAllocLIR);
+                    ArmLIR *newAdr = (ArmLIR *)oatNew(cUnit, sizeof(ArmLIR),
+                        true, kAllocLIR);
                     newAdr->generic.dalvikOffset = lir->generic.dalvikOffset;
                     newAdr->generic.target = lir->generic.target;
                     newAdr->opcode = kThumb2Adr;
@@ -1165,8 +1165,8 @@
                 int delta = target - pc;
                 if (delta > 126 || delta < 0) {
                     /* Convert to cmp rx,#0 / b[eq/ne] tgt pair */
-                    ArmLIR *newInst =
-                        (ArmLIR *)oatNew(sizeof(ArmLIR), true, kAllocLIR);
+                    ArmLIR *newInst = (ArmLIR *)oatNew(cUnit, sizeof(ArmLIR),
+                        true, kAllocLIR);
                     /* Make new branch instruction and insert after */
                     newInst->generic.dalvikOffset = lir->generic.dalvikOffset;
                     newInst->opcode = kThumbBCond;
@@ -1290,7 +1290,8 @@
                 } else {
                     // convert to ldimm16l, ldimm16h, add tgt, pc, operands[0]
                     ArmLIR *newMov16L =
-                        (ArmLIR *)oatNew(sizeof(ArmLIR), true, kAllocLIR);
+                        (ArmLIR *)oatNew(cUnit, sizeof(ArmLIR), true,
+                        kAllocLIR);
                     newMov16L->generic.dalvikOffset = lir->generic.dalvikOffset;
                     newMov16L->generic.target = lir->generic.target;
                     newMov16L->opcode = kThumb2MovImm16LST;
@@ -1300,7 +1301,8 @@
                     oatSetupResourceMasks(newMov16L);
                     oatInsertLIRBefore((LIR*)lir, (LIR*)newMov16L);
                     ArmLIR *newMov16H =
-                        (ArmLIR *)oatNew(sizeof(ArmLIR), true, kAllocLIR);
+                        (ArmLIR *)oatNew(cUnit, sizeof(ArmLIR), true,
+                        kAllocLIR);
                     newMov16H->generic.dalvikOffset = lir->generic.dalvikOffset;
                     newMov16H->generic.target = lir->generic.target;
                     newMov16H->opcode = kThumb2MovImm16HST;
@@ -1345,7 +1347,7 @@
         if (res != kSuccess) {
             continue;
         }
-        ArmEncodingMap *encoder = &EncodingMap[lir->opcode];
+        const ArmEncodingMap *encoder = &EncodingMap[lir->opcode];
         u4 bits = encoder->skeleton;
         int i;
         for (i = 0; i < 4; i++) {
diff --git a/src/compiler/codegen/arm/CodegenCommon.cc b/src/compiler/codegen/arm/CodegenCommon.cc
index c99573f..fb6ad30 100644
--- a/src/compiler/codegen/arm/CodegenCommon.cc
+++ b/src/compiler/codegen/arm/CodegenCommon.cc
@@ -245,7 +245,7 @@
  */
 STATIC ArmLIR* newLIR0(CompilationUnit* cUnit, ArmOpcode opcode)
 {
-    ArmLIR* insn = (ArmLIR* ) oatNew(sizeof(ArmLIR), true, kAllocLIR);
+    ArmLIR* insn = (ArmLIR* ) oatNew(cUnit, sizeof(ArmLIR), true, kAllocLIR);
     DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & NO_OPERAND));
     insn->opcode = opcode;
     setupResourceMasks(insn);
@@ -257,7 +257,7 @@
 STATIC ArmLIR* newLIR1(CompilationUnit* cUnit, ArmOpcode opcode,
                            int dest)
 {
-    ArmLIR* insn = (ArmLIR* ) oatNew(sizeof(ArmLIR), true, kAllocLIR);
+    ArmLIR* insn = (ArmLIR* ) oatNew(cUnit, sizeof(ArmLIR), true, kAllocLIR);
     DCHECK(isPseudoOpcode(opcode) || (EncodingMap[opcode].flags & IS_UNARY_OP));
     insn->opcode = opcode;
     insn->operands[0] = dest;
@@ -270,7 +270,7 @@
 STATIC ArmLIR* newLIR2(CompilationUnit* cUnit, ArmOpcode opcode,
                            int dest, int src1)
 {
-    ArmLIR* insn = (ArmLIR* ) oatNew(sizeof(ArmLIR), true, kAllocLIR);
+    ArmLIR* insn = (ArmLIR* ) oatNew(cUnit, sizeof(ArmLIR), true, kAllocLIR);
     DCHECK(isPseudoOpcode(opcode) ||
            (EncodingMap[opcode].flags & IS_BINARY_OP));
     insn->opcode = opcode;
@@ -285,7 +285,7 @@
 STATIC ArmLIR* newLIR3(CompilationUnit* cUnit, ArmOpcode opcode,
                            int dest, int src1, int src2)
 {
-    ArmLIR* insn = (ArmLIR* ) oatNew(sizeof(ArmLIR), true, kAllocLIR);
+    ArmLIR* insn = (ArmLIR* ) oatNew(cUnit, sizeof(ArmLIR), true, kAllocLIR);
     DCHECK(isPseudoOpcode(opcode) ||
            (EncodingMap[opcode].flags & IS_TERTIARY_OP))
             << (int)opcode << " "
@@ -305,7 +305,7 @@
 STATIC ArmLIR* newLIR4(CompilationUnit* cUnit, ArmOpcode opcode,
                            int dest, int src1, int src2, int info)
 {
-    ArmLIR* insn = (ArmLIR* ) oatNew(sizeof(ArmLIR), true, kAllocLIR);
+    ArmLIR* insn = (ArmLIR* ) oatNew(cUnit, sizeof(ArmLIR), true, kAllocLIR);
     DCHECK(isPseudoOpcode(opcode) ||
            (EncodingMap[opcode].flags & IS_QUAD_OP));
     insn->opcode = opcode;
@@ -365,7 +365,8 @@
 {
     /* Add the constant to the literal pool */
     if (constantListP) {
-        ArmLIR* newValue = (ArmLIR* ) oatNew(sizeof(ArmLIR), true, kAllocData);
+        ArmLIR* newValue = (ArmLIR* ) oatNew(cUnit, sizeof(ArmLIR), true,
+                                             kAllocData);
         newValue->operands[0] = value;
         newValue->generic.next = *constantListP;
         *constantListP = (LIR*) newValue;
diff --git a/src/compiler/codegen/arm/LocalOptimizations.cc b/src/compiler/codegen/arm/LocalOptimizations.cc
index 2883209..9098627 100644
--- a/src/compiler/codegen/arm/LocalOptimizations.cc
+++ b/src/compiler/codegen/arm/LocalOptimizations.cc
@@ -236,7 +236,8 @@
                 /* Only sink store instructions */
                 if (sinkDistance && !isThisLIRLoad) {
                     ArmLIR* newStoreLIR =
-                        (ArmLIR* ) oatNew(sizeof(ArmLIR), true, kAllocLIR);
+                        (ArmLIR* ) oatNew(cUnit, sizeof(ArmLIR), true,
+                                          kAllocLIR);
                     *newStoreLIR = *thisLIR;
                     /*
                      * Stop point found - insert *before* the checkLIR
@@ -423,7 +424,7 @@
             /* Found a slot to hoist to */
             if (slot >= 0) {
                 ArmLIR* curLIR = prevInstList[slot];
-                ArmLIR* newLoadLIR = (ArmLIR* ) oatNew(sizeof(ArmLIR),
+                ArmLIR* newLoadLIR = (ArmLIR* ) oatNew(cUnit, sizeof(ArmLIR),
                                                        true, kAllocLIR);
                 *newLoadLIR = *thisLIR;
                 /*
diff --git a/src/compiler/codegen/arm/MethodCodegenDriver.cc b/src/compiler/codegen/arm/MethodCodegenDriver.cc
index 1efab12..6866423 100644
--- a/src/compiler/codegen/arm/MethodCodegenDriver.cc
+++ b/src/compiler/codegen/arm/MethodCodegenDriver.cc
@@ -1861,8 +1861,8 @@
     int opOffset = mir->dalvikInsn.opcode - kMirOpFirst;
     char* msg = NULL;
     if (cUnit->printMe) {
-        msg = (char*)oatNew(strlen(extendedMIROpNames[opOffset]) + 1, false,
-                            kAllocDebugInfo);
+        msg = (char*)oatNew(cUnit, strlen(extendedMIROpNames[opOffset]) + 1,
+                            false, kAllocDebugInfo);
         strcpy(msg, extendedMIROpNames[opOffset]);
     }
     ArmLIR* op = newLIR1(cUnit, kArmPseudoExtended, (int) msg);
@@ -2051,7 +2051,7 @@
 
         /* Mark the beginning of a Dalvik instruction for line tracking */
         char* instStr = cUnit->printMe ?
-           oatGetDalvikDisassembly(&mir->dalvikInsn, "") : NULL;
+           oatGetDalvikDisassembly(cUnit, &mir->dalvikInsn, "") : NULL;
         boundaryLIR = newLIR1(cUnit, kArmPseudoDalvikByteCodeBoundary,
                               (intptr_t) instStr);
         cUnit->boundaryMap.insert(std::make_pair(mir->offset,
@@ -2235,7 +2235,8 @@
 {
     /* Used to hold the labels of each block */
     cUnit->blockLabelList =
-        (void *) oatNew(sizeof(ArmLIR) * cUnit->numBlocks, true, kAllocLIR);
+        (void *) oatNew(cUnit, sizeof(ArmLIR) * cUnit->numBlocks, true,
+                        kAllocLIR);
 
     oatDataFlowAnalysisDispatcher(cUnit, methodBlockCodeGen,
                                   kPreOrderDFSTraversal, false /* Iterative */);
diff --git a/src/compiler/codegen/arm/Thumb2/Factory.cc b/src/compiler/codegen/arm/Thumb2/Factory.cc
index 34ffa60..9b7d299 100644
--- a/src/compiler/codegen/arm/Thumb2/Factory.cc
+++ b/src/compiler/codegen/arm/Thumb2/Factory.cc
@@ -69,7 +69,8 @@
     if (dataTarget == NULL) {
         dataTarget = addWordData(cUnit, &cUnit->literalList, value);
     }
-    ArmLIR* loadPcRel = (ArmLIR* ) oatNew(sizeof(ArmLIR), true, kAllocLIR);
+    ArmLIR* loadPcRel = (ArmLIR* ) oatNew(cUnit, sizeof(ArmLIR), true,
+                                          kAllocLIR);
     loadPcRel->generic.dalvikOffset = cUnit->currentDalvikOffset;
     loadPcRel->opcode = kThumb2Vldrs;
     loadPcRel->generic.target = (LIR* ) dataTarget;
@@ -178,7 +179,8 @@
     if (dataTarget == NULL) {
         dataTarget = addWordData(cUnit, &cUnit->literalList, value);
     }
-    ArmLIR* loadPcRel = (ArmLIR* ) oatNew(sizeof(ArmLIR), true, kAllocLIR);
+    ArmLIR* loadPcRel = (ArmLIR* ) oatNew(cUnit, sizeof(ArmLIR), true,
+                                          kAllocLIR);
     loadPcRel->opcode = kThumb2LdrPcRel12;
     loadPcRel->generic.target = (LIR* ) dataTarget;
     loadPcRel->generic.dalvikOffset = cUnit->currentDalvikOffset;
@@ -655,7 +657,7 @@
                 dataTarget = addWideData(cUnit, &cUnit->literalList, valLo,
                                          valHi);
             }
-            ArmLIR* loadPcRel = (ArmLIR* ) oatNew(sizeof(ArmLIR), true,
+            ArmLIR* loadPcRel = (ArmLIR* ) oatNew(cUnit, sizeof(ArmLIR), true,
                                                   kAllocLIR);
             loadPcRel->generic.dalvikOffset = cUnit->currentDalvikOffset;
             loadPcRel->opcode = kThumb2Vldrd;
@@ -1072,7 +1074,7 @@
 
 STATIC ArmLIR* fpRegCopy(CompilationUnit* cUnit, int rDest, int rSrc)
 {
-    ArmLIR* res = (ArmLIR* ) oatNew(sizeof(ArmLIR), true, kAllocLIR);
+    ArmLIR* res = (ArmLIR* ) oatNew(cUnit, sizeof(ArmLIR), true, kAllocLIR);
     res->generic.dalvikOffset = cUnit->currentDalvikOffset;
     res->operands[0] = rDest;
     res->operands[1] = rSrc;
@@ -1103,7 +1105,7 @@
     ArmOpcode opcode;
     if (FPREG(rDest) || FPREG(rSrc))
         return fpRegCopy(cUnit, rDest, rSrc);
-    res = (ArmLIR* ) oatNew(sizeof(ArmLIR), true, kAllocLIR);
+    res = (ArmLIR* ) oatNew(cUnit, sizeof(ArmLIR), true, kAllocLIR);
     res->generic.dalvikOffset = cUnit->currentDalvikOffset;
     if (LOWREG(rDest) && LOWREG(rSrc))
         opcode = kThumbMovRR;
diff --git a/src/compiler/codegen/arm/Thumb2/Gen.cc b/src/compiler/codegen/arm/Thumb2/Gen.cc
index fe0d3f2..042ebb2 100644
--- a/src/compiler/codegen/arm/Thumb2/Gen.cc
+++ b/src/compiler/codegen/arm/Thumb2/Gen.cc
@@ -134,7 +134,7 @@
     if (it == cUnit->boundaryMap.end()) {
         LOG(FATAL) << "Error: didn't find vaddr 0x" << std::hex << vaddr;
     }
-    ArmLIR* newLabel = (ArmLIR*)oatNew(sizeof(ArmLIR), true, kAllocLIR);
+    ArmLIR* newLabel = (ArmLIR*)oatNew(cUnit, sizeof(ArmLIR), true, kAllocLIR);
     newLabel->generic.dalvikOffset = vaddr;
     newLabel->opcode = kArmPseudoCaseLabel;
     newLabel->operands[0] = keyVal;
@@ -259,14 +259,14 @@
         dumpSparseSwitchTable(table);
     }
     // Add the table to the list - we'll process it later
-    SwitchTable *tabRec = (SwitchTable *)oatNew(sizeof(SwitchTable),
+    SwitchTable *tabRec = (SwitchTable *)oatNew(cUnit, sizeof(SwitchTable),
                          true, kAllocData);
     tabRec->table = table;
     tabRec->vaddr = mir->offset;
     int size = table[1];
-    tabRec->targets = (ArmLIR* *)oatNew(size * sizeof(ArmLIR*), true,
+    tabRec->targets = (ArmLIR* *)oatNew(cUnit, size * sizeof(ArmLIR*), true,
                                         kAllocLIR);
-    oatInsertGrowableList(&cUnit->switchTables, (intptr_t)tabRec);
+    oatInsertGrowableList(cUnit, &cUnit->switchTables, (intptr_t)tabRec);
 
     // Get the switch value
     rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
@@ -310,14 +310,14 @@
         dumpPackedSwitchTable(table);
     }
     // Add the table to the list - we'll process it later
-    SwitchTable *tabRec = (SwitchTable *)oatNew(sizeof(SwitchTable),
+    SwitchTable *tabRec = (SwitchTable *)oatNew(cUnit, sizeof(SwitchTable),
                                                 true, kAllocData);
     tabRec->table = table;
     tabRec->vaddr = mir->offset;
     int size = table[1];
-    tabRec->targets = (ArmLIR* *)oatNew(size * sizeof(ArmLIR*), true,
+    tabRec->targets = (ArmLIR* *)oatNew(cUnit, size * sizeof(ArmLIR*), true,
                                         kAllocLIR);
-    oatInsertGrowableList(&cUnit->switchTables, (intptr_t)tabRec);
+    oatInsertGrowableList(cUnit, &cUnit->switchTables, (intptr_t)tabRec);
 
     // Get the switch value
     rlSrc = loadValue(cUnit, rlSrc, kCoreReg);
@@ -367,14 +367,14 @@
     const u2* table = cUnit->insns + mir->offset + mir->dalvikInsn.vB;
     // Add the table to the list - we'll process it later
     FillArrayData *tabRec = (FillArrayData *)
-         oatNew(sizeof(FillArrayData), true, kAllocData);
+         oatNew(cUnit, sizeof(FillArrayData), true, kAllocData);
     tabRec->table = table;
     tabRec->vaddr = mir->offset;
     u2 width = tabRec->table[1];
     u4 size = tabRec->table[2] | (((u4)tabRec->table[3]) << 16);
     tabRec->size = (size * width) + 8;
 
-    oatInsertGrowableList(&cUnit->fillArrayData, (intptr_t)tabRec);
+    oatInsertGrowableList(cUnit, &cUnit->fillArrayData, (intptr_t)tabRec);
 
     // Making a call - use explicit registers
     oatFlushAllRegs(cUnit);   /* Everything to home location */
@@ -934,17 +934,17 @@
     int numTemps = sizeof(coreTemps)/sizeof(*coreTemps);
     int numFPRegs = sizeof(fpRegs)/sizeof(*fpRegs);
     int numFPTemps = sizeof(fpTemps)/sizeof(*fpTemps);
-    RegisterPool *pool = (RegisterPool *)oatNew(sizeof(*pool), true,
+    RegisterPool *pool = (RegisterPool *)oatNew(cUnit, sizeof(*pool), true,
                                                 kAllocRegAlloc);
     cUnit->regPool = pool;
     pool->numCoreRegs = numRegs;
     pool->coreRegs = (RegisterInfo *)
-            oatNew(numRegs * sizeof(*cUnit->regPool->coreRegs), true,
-                   kAllocRegAlloc);
+            oatNew(cUnit, numRegs * sizeof(*cUnit->regPool->coreRegs),
+                   true, kAllocRegAlloc);
     pool->numFPRegs = numFPRegs;
     pool->FPRegs = (RegisterInfo *)
-            oatNew(numFPRegs * sizeof(*cUnit->regPool->FPRegs), true,
-                                      kAllocRegAlloc);
+            oatNew(cUnit, numFPRegs * sizeof(*cUnit->regPool->FPRegs), true,
+                   kAllocRegAlloc);
     oatInitPool(pool->coreRegs, coreRegs, pool->numCoreRegs);
     oatInitPool(pool->FPRegs, fpRegs, pool->numFPRegs);
     // Keep special registers from being allocated
@@ -963,7 +963,7 @@
         oatMarkTemp(cUnit, fpTemps[i]);
     }
     // Construct the alias map.
-    cUnit->phiAliasMap = (int*)oatNew(cUnit->numSSARegs *
+    cUnit->phiAliasMap = (int*)oatNew(cUnit, cUnit->numSSARegs *
                                       sizeof(cUnit->phiAliasMap[0]), false,
                                       kAllocDFInfo);
     for (int i = 0; i < cUnit->numSSARegs; i++) {
@@ -1816,13 +1816,13 @@
     ArmLIR* branch = opCondBranch(cUnit, kArmCondEq);
     ArmLIR* retLab = newLIR0(cUnit, kArmPseudoTargetLabel);
     retLab->defMask = ENCODE_ALL;
-    ArmLIR* target = (ArmLIR*)oatNew(sizeof(ArmLIR), true, kAllocLIR);
+    ArmLIR* target = (ArmLIR*)oatNew(cUnit, sizeof(ArmLIR), true, kAllocLIR);
     target->generic.dalvikOffset = cUnit->currentDalvikOffset;
     target->opcode = kArmPseudoSuspendTarget;
     target->operands[0] = (intptr_t)retLab;
     target->operands[1] = mir->offset;
     branch->generic.target = (LIR*)target;
-    oatInsertGrowableList(&cUnit->suspendLaunchpads, (intptr_t)target);
+    oatInsertGrowableList(cUnit, &cUnit->suspendLaunchpads, (intptr_t)target);
 }
 
 /*