Fixed OOM exception handling in JIT'ed code and added a new unit test.
diff --git a/vm/compiler/codegen/arm/Codegen.c b/vm/compiler/codegen/arm/Codegen.c
index d65023d..30a7b1b 100644
--- a/vm/compiler/codegen/arm/Codegen.c
+++ b/vm/compiler/codegen/arm/Codegen.c
@@ -810,7 +810,7 @@
 {
     ArmLIR *res;
     res = opRegReg(cUnit, OP_CMP, reg1, reg2);
-    ArmLIR *branch = opImmImm(cUnit, OP_COND_BR, 0, cond);
+    ArmLIR *branch = opCondBranch(cUnit, cond);
     genCheckCommon(cUnit, dOffset, branch, pcrLabel);
     return res;
 }
@@ -1851,8 +1851,7 @@
     /* Check if rechain limit is reached */
     opRegImm(cUnit, OP_CMP, r1, 0, rNone);
 
-    ArmLIR *bypassRechaining =
-        opImmImm(cUnit, OP_COND_BR, 0, ARM_COND_GT);
+    ArmLIR *bypassRechaining = opCondBranch(cUnit, ARM_COND_GT);
 
     loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
                  jitToInterpEntries.dvmJitToPatchPredictedChain), r7);
@@ -1936,7 +1935,7 @@
     /* Check if r2 (predicted class) == r3 (actual class) */
     opRegReg(cUnit, OP_CMP, r2, r3);
 
-    return opImmImm(cUnit, OP_COND_BR, 0, ARM_COND_EQ);
+    return opCondBranch(cUnit, ARM_COND_EQ);
 }
 
 /* Geneate a branch to go back to the interpreter */
@@ -1978,7 +1977,7 @@
                                     ArmConditionCode cond,
                                     ArmLIR *target)
 {
-    ArmLIR *branch = opImmImm(cUnit, OP_COND_BR, 0, cond);
+    ArmLIR *branch = opCondBranch(cUnit, cond);
     branch->generic.target = (LIR *) target;
     return branch;
 }
@@ -2327,7 +2326,20 @@
             genExportPC(cUnit, mir, r2, r3 );
             loadConstant(cUnit, r1, ALLOC_DONT_TRACK);
             opReg(cUnit, OP_BLX, r4PC);
-            genZeroCheck(cUnit, r0, mir->offset, NULL);
+            /* generate a branch over if allocation is successful */
+            opRegImm(cUnit, OP_CMP, r0, 0, rNone); /* NULL? */
+            ArmLIR *branchOver = opCondBranch(cUnit, ARM_COND_NE);
+            /*
+             * OOM exception needs to be thrown here and cannot re-execute
+             */
+            loadConstant(cUnit, r0,
+                         (int) (cUnit->method->insns + mir->offset));
+            genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON);
+            /* noreturn */
+
+            ArmLIR *target = newLIR0(cUnit, ARM_PSEUDO_TARGET_LABEL);
+            target->defMask = ENCODE_ALL;
+            branchOver->generic.target = (LIR *) target;
             storeValue(cUnit, r0, mir->dalvikInsn.vA, r1);
             break;
         }
@@ -2341,14 +2353,12 @@
             loadConstant(cUnit, r1, (int) classPtr );
             loadValue(cUnit, mir->dalvikInsn.vA, r0);  /* Ref */
             opRegImm(cUnit, OP_CMP, r0, 0, rNone);   /* Null? */
-            ArmLIR *branch1 =
-                opImmImm(cUnit, OP_COND_BR, 4, ARM_COND_EQ);
+            ArmLIR *branch1 = opCondBranch(cUnit, ARM_COND_EQ);
             /* r0 now contains object->clazz */
             loadWordDisp(cUnit, r0, offsetof(Object, clazz), r0);
             loadConstant(cUnit, r4PC, (int)dvmInstanceofNonTrivial);
             opRegReg(cUnit, OP_CMP, r0, r1);
-            ArmLIR *branch2 =
-                opImmImm(cUnit, OP_COND_BR, 2, ARM_COND_EQ);
+            ArmLIR *branch2 = opCondBranch(cUnit, ARM_COND_EQ);
             opReg(cUnit, OP_BLX, r4PC);
             /* check cast failed - punt to the interpreter */
             genZeroCheck(cUnit, r0, mir->offset, NULL);
@@ -2658,7 +2668,7 @@
     int vSrc = mir->dalvikInsn.vB;
     int vDest = mir->dalvikInsn.vA;
     int lit = mir->dalvikInsn.vC;
-    OpKind op;
+    OpKind op = 0;      /* Make gcc happy */
     int reg0, reg1, regDest;
 
     reg0 = selectFirstRegister(cUnit, vSrc, false);
@@ -2800,13 +2810,29 @@
             loadValue(cUnit, mir->dalvikInsn.vB, r1);  /* Len */
             loadConstant(cUnit, r0, (int) classPtr );
             loadConstant(cUnit, r4PC, (int)dvmAllocArrayByClass);
+            /*
+             * "len < 0": bail to the interpreter to re-execute the
+             * instruction
+             */
             ArmLIR *pcrLabel =
                 genRegImmCheck(cUnit, ARM_COND_MI, r1, 0, mir->offset, NULL);
             genExportPC(cUnit, mir, r2, r3 );
             loadConstant(cUnit, r2, ALLOC_DONT_TRACK);
             opReg(cUnit, OP_BLX, r4PC);
-            /* Note: on failure, we'll bail and reinterpret */
-            genZeroCheck(cUnit, r0, mir->offset, pcrLabel);
+            /* generate a branch over if allocation is successful */
+            opRegImm(cUnit, OP_CMP, r0, 0, rNone); /* NULL? */
+            ArmLIR *branchOver = opCondBranch(cUnit, ARM_COND_NE);
+            /*
+             * OOM exception needs to be thrown here and cannot re-execute
+             */
+            loadConstant(cUnit, r0,
+                         (int) (cUnit->method->insns + mir->offset));
+            genDispatchToHandler(cUnit, TEMPLATE_THROW_EXCEPTION_COMMON);
+            /* noreturn */
+
+            ArmLIR *target = newLIR0(cUnit, ARM_PSEUDO_TARGET_LABEL);
+            target->defMask = ENCODE_ALL;
+            branchOver->generic.target = (LIR *) target;
             storeValue(cUnit, r0, mir->dalvikInsn.vA, r1);
             break;
         }
@@ -2819,13 +2845,13 @@
 //TUNING: compare to 0 primative to allow use of CB[N]Z
             opRegImm(cUnit, OP_CMP, r0, 0, rNone); /* NULL? */
             /* When taken r0 has NULL which can be used for store directly */
-            ArmLIR *branch1 = opImmImm(cUnit, OP_COND_BR, 4, ARM_COND_EQ);
+            ArmLIR *branch1 = opCondBranch(cUnit, ARM_COND_EQ);
             /* r1 now contains object->clazz */
             loadWordDisp(cUnit, r0, offsetof(Object, clazz), r1);
             loadConstant(cUnit, r4PC, (int)dvmInstanceofNonTrivial);
             loadConstant(cUnit, r0, 1);                /* Assume true */
             opRegReg(cUnit, OP_CMP, r1, r2);
-            ArmLIR *branch2 = opImmImm(cUnit, OP_COND_BR, 2, ARM_COND_EQ);
+            ArmLIR *branch2 = opCondBranch(cUnit, ARM_COND_EQ);
             opRegReg(cUnit, OP_MOV, r0, r1);
             opRegReg(cUnit, OP_MOV, r1, r2);
             opReg(cUnit, OP_BLX, r4PC);
@@ -3345,8 +3371,7 @@
             /* Check if rechain limit is reached */
             opRegImm(cUnit, OP_CMP, r1, 0, rNone);
 
-            ArmLIR *bypassRechaining =
-                opImmImm(cUnit, OP_COND_BR, 0, ARM_COND_GT);
+            ArmLIR *bypassRechaining = opCondBranch(cUnit, ARM_COND_GT);
 
             loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
                          jitToInterpEntries.dvmJitToPatchPredictedChain), r7);
diff --git a/vm/compiler/codegen/arm/Thumb2Util.c b/vm/compiler/codegen/arm/Thumb2Util.c
index b40656d..dfbb030 100644
--- a/vm/compiler/codegen/arm/Thumb2Util.c
+++ b/vm/compiler/codegen/arm/Thumb2Util.c
@@ -68,8 +68,7 @@
 
 static ArmLIR *opNone(CompilationUnit *cUnit, OpKind op);
 static ArmLIR *opImm(CompilationUnit *cUnit, OpKind op, int value);
-static ArmLIR *opImmImm(CompilationUnit *cUnit, OpKind op, int value1,
-                        int value2);
+static ArmLIR *opCondBranch(CompilationUnit *cUnit, ArmConditionCode cc);
 static ArmLIR *opReg(CompilationUnit *cUnit, OpKind op, int rDestSrc);
 static ArmLIR *opRegReg(CompilationUnit *cUnit, OpKind op, int rDestSrc1,
                         int rSrc2);
@@ -795,18 +794,9 @@
     return newLIR0(cUnit, opCode);
 }
 
-static ArmLIR *opImmImm(CompilationUnit *cUnit, OpKind op, int value1,
-                        int value2)
+static ArmLIR *opCondBranch(CompilationUnit *cUnit, ArmConditionCode cc)
 {
-    ArmOpCode opCode = THUMB_BKPT;
-    switch (op) {
-        case OP_COND_BR:
-            opCode = THUMB_B_COND;
-            break;
-        default:
-            assert(0);
-    }
-    return newLIR2(cUnit, opCode, value1, value2);
+    return newLIR2(cUnit, THUMB_B_COND, 0 /* offset to be patched */, cc);
 }
 
 static ArmLIR *opImm(CompilationUnit *cUnit, OpKind op, int value)
@@ -1210,10 +1200,10 @@
     /* Note: using hardcoded r7 & r4PC for now.  revisit */
     loadConstant(cUnit, r7, -1);
     opRegReg(cUnit, OP_CMP, op1hi, op2hi);
-    ArmLIR *branch1 = opImmImm(cUnit, OP_COND_BR, 0, ARM_COND_LT);
-    ArmLIR *branch2 = opImmImm(cUnit, OP_COND_BR, 0, ARM_COND_GT);
+    ArmLIR *branch1 = opCondBranch(cUnit, ARM_COND_LT);
+    ArmLIR *branch2 = opCondBranch(cUnit, ARM_COND_GT);
     opRegRegReg(cUnit, OP_SUB, r7, op1lo, op2lo);
-    ArmLIR *branch3 = opImmImm(cUnit, OP_COND_BR, 0, ARM_COND_EQ);
+    ArmLIR *branch3 = opCondBranch(cUnit, ARM_COND_EQ);
 
     // TODO: need assert mechanism to verify IT block size
     branch1->generic.target = (LIR *) genIT(cUnit, ARM_COND_HI, "E");
diff --git a/vm/compiler/codegen/arm/ThumbUtil.c b/vm/compiler/codegen/arm/ThumbUtil.c
index 49e04b4..4065865 100644
--- a/vm/compiler/codegen/arm/ThumbUtil.c
+++ b/vm/compiler/codegen/arm/ThumbUtil.c
@@ -72,8 +72,7 @@
 
 static ArmLIR *opNone(CompilationUnit *cUnit, OpKind op);
 static ArmLIR *opImm(CompilationUnit *cUnit, OpKind op, int value);
-static ArmLIR *opImmImm(CompilationUnit *cUnit, OpKind op, int value1,
-                        int value2);
+static ArmLIR *opCondBranch(CompilationUnit *cUnit, ArmConditionCode cc);
 static ArmLIR *opReg(CompilationUnit *cUnit, OpKind op, int rDestSrc);
 static ArmLIR *opRegReg(CompilationUnit *cUnit, OpKind op, int rDestSrc1,
                         int rSrc2);
@@ -493,18 +492,9 @@
     return newLIR0(cUnit, opCode);
 }
 
-static ArmLIR *opImmImm(CompilationUnit *cUnit, OpKind op, int value1,
-                        int value2)
+static ArmLIR *opCondBranch(CompilationUnit *cUnit, ArmConditionCode cc)
 {
-    ArmOpCode opCode = THUMB_BKPT;
-    switch (op) {
-        case OP_COND_BR:
-            opCode = THUMB_B_COND;
-            break;
-        default:
-            assert(0);
-    }
-    return newLIR2(cUnit, opCode, value1, value2);
+    return newLIR2(cUnit, THUMB_B_COND, 0 /* offset to be patched */, cc);
 }
 
 static ArmLIR *opImm(CompilationUnit *cUnit, OpKind op, int value)