Fixed OOM exception handling in JIT'ed code and added a new unit test.
diff --git a/tests/080-oom-throw/expected.txt b/tests/080-oom-throw/expected.txt
new file mode 100644
index 0000000..811f68c
--- /dev/null
+++ b/tests/080-oom-throw/expected.txt
@@ -0,0 +1,2 @@
+Array allocation failed
+Instance allocation failed
diff --git a/tests/080-oom-throw/info.txt b/tests/080-oom-throw/info.txt
new file mode 100644
index 0000000..e8ae6f6
--- /dev/null
+++ b/tests/080-oom-throw/info.txt
@@ -0,0 +1,3 @@
+Inject memory allocation failures for NEW_ARRAY and NEW_INSTANCE and make sure
+the JIT'ed code handles OOM exception correctly since it cannot fall back to
+the interpreter and re-execute the bytecode.
diff --git a/tests/080-oom-throw/src/Main.java b/tests/080-oom-throw/src/Main.java
new file mode 100644
index 0000000..3d75f3d
--- /dev/null
+++ b/tests/080-oom-throw/src/Main.java
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2009 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+public class Main {
+    static class ArrayMemEater {
+        static int blowup(char[][] holder, int size) {
+            int i = 0;
+            try {
+                for ( ; i < size; i++)
+                    holder[i] = new char[128];
+            } catch (OutOfMemoryError oome) {
+                return i;
+            }
+
+            return size;
+        }
+
+        static void confuseCompilerOptimization(char[][] holder) {
+        }
+    }
+
+    static class InstanceMemEater {
+        InstanceMemEater next;
+        double d1, d2, d3, d4, d5, d6, d7, d8;
+
+        static InstanceMemEater blowup() {
+            InstanceMemEater memEater;
+            try {
+                memEater = new InstanceMemEater();
+            } catch (OutOfMemoryError e) {
+                memEater = null;
+            }
+            return memEater;
+        }
+
+        static void confuseCompilerOptimization(InstanceMemEater memEater) {
+        }
+    }
+
+    static void triggerArrayOOM() {
+        int size = 1 * 1024 * 1024;
+        char[][] holder = new char[size][];
+
+        int count = ArrayMemEater.blowup(holder, size);
+        ArrayMemEater.confuseCompilerOptimization(holder);
+        if (count < size) {
+            System.out.println("Array allocation failed");
+        }
+    }
+
+    static void triggerInstanceOOM() {
+        InstanceMemEater memEater = InstanceMemEater.blowup();
+        InstanceMemEater lastMemEater = memEater;
+        do {
+            lastMemEater.next = InstanceMemEater.blowup();
+            lastMemEater = lastMemEater.next;
+        } while (lastMemEater != null);
+        memEater.confuseCompilerOptimization(memEater);
+        System.out.println("Instance allocation failed");
+    }
+
+    public static void main(String[] args) {
+        triggerArrayOOM();
+        triggerInstanceOOM();
+    }
+}
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)
diff --git a/vm/compiler/template/armv5te-vfp/TemplateOpList.h b/vm/compiler/template/armv5te-vfp/TemplateOpList.h
index c95163c..6d1ce67 100644
--- a/vm/compiler/template/armv5te-vfp/TemplateOpList.h
+++ b/vm/compiler/template/armv5te-vfp/TemplateOpList.h
@@ -50,3 +50,4 @@
 JIT_TEMPLATE(CMPG_FLOAT_VFP)
 JIT_TEMPLATE(CMPL_FLOAT_VFP)
 JIT_TEMPLATE(SQRT_DOUBLE_VFP)
+JIT_TEMPLATE(THROW_EXCEPTION_COMMON)
diff --git a/vm/compiler/template/armv5te/TEMPLATE_THROW_EXCEPTION_COMMON.S b/vm/compiler/template/armv5te/TEMPLATE_THROW_EXCEPTION_COMMON.S
new file mode 100644
index 0000000..b737798
--- /dev/null
+++ b/vm/compiler/template/armv5te/TEMPLATE_THROW_EXCEPTION_COMMON.S
@@ -0,0 +1,6 @@
+    /*
+     * Throw an exception from JIT'ed code.
+     * On entry:
+     *    r0    Dalvik PC that raises the exception
+     */
+    b       .LhandleException
diff --git a/vm/compiler/template/armv5te/TemplateOpList.h b/vm/compiler/template/armv5te/TemplateOpList.h
index 39cd07a..20fb7fa 100644
--- a/vm/compiler/template/armv5te/TemplateOpList.h
+++ b/vm/compiler/template/armv5te/TemplateOpList.h
@@ -35,3 +35,4 @@
 JIT_TEMPLATE(SHL_LONG)
 JIT_TEMPLATE(SHR_LONG)
 JIT_TEMPLATE(USHR_LONG)
+JIT_TEMPLATE(THROW_EXCEPTION_COMMON)
diff --git a/vm/compiler/template/armv5te/footer.S b/vm/compiler/template/armv5te/footer.S
index 3b0b149..c373250 100644
--- a/vm/compiler/template/armv5te/footer.S
+++ b/vm/compiler/template/armv5te/footer.S
@@ -31,15 +31,19 @@
     str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
     cmp     r1, #0                      @ null?
     str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
+    ldr     r0, [r10, #offStackSaveArea_savedPc] @ reload rPC
     bne     .LhandleException             @ no, handle exception
     bx      r2
 
-/* NOTE - this path can be exercised if the JIT threshold is set to 5 */
+/*
+ * On entry:
+ * r0  Faulting Dalvik PC
+ */
 .LhandleException:
-    ldr     r0, .LdvmMterpCommonExceptionThrown @ PIC way of getting &func
+    ldr     r1, .LdvmMterpCommonExceptionThrown @ PIC way of getting &func
     ldr     rIBASE, .LdvmAsmInstructionStart    @ same as above
-    ldr     rPC, [r10, #offStackSaveArea_savedPc] @ reload rPC
-    mov     pc, r0                  @ branch to dvmMterpCommonExceptionThrown
+    mov     rPC, r0                 @ reload the faulting Dalvik address
+    mov     pc, r1                  @ branch to dvmMterpCommonExceptionThrown
 
     .align  2
 .LdvmAsmInstructionStart:
diff --git a/vm/compiler/template/armv7-a/TemplateOpList.h b/vm/compiler/template/armv7-a/TemplateOpList.h
index c95163c..6d1ce67 100644
--- a/vm/compiler/template/armv7-a/TemplateOpList.h
+++ b/vm/compiler/template/armv7-a/TemplateOpList.h
@@ -50,3 +50,4 @@
 JIT_TEMPLATE(CMPG_FLOAT_VFP)
 JIT_TEMPLATE(CMPL_FLOAT_VFP)
 JIT_TEMPLATE(SQRT_DOUBLE_VFP)
+JIT_TEMPLATE(THROW_EXCEPTION_COMMON)
diff --git a/vm/compiler/template/config-armv5te-vfp b/vm/compiler/template/config-armv5te-vfp
index 628e75f..ab3ff90 100644
--- a/vm/compiler/template/config-armv5te-vfp
+++ b/vm/compiler/template/config-armv5te-vfp
@@ -42,6 +42,7 @@
     op TEMPLATE_SHL_LONG armv5te
     op TEMPLATE_SHR_LONG armv5te
     op TEMPLATE_USHR_LONG armv5te
+    op TEMPLATE_THROW_EXCEPTION_COMMON armv5te
 
 op-end
 
diff --git a/vm/compiler/template/config-armv7-a b/vm/compiler/template/config-armv7-a
index ecf0b3a..aed0fa7 100644
--- a/vm/compiler/template/config-armv7-a
+++ b/vm/compiler/template/config-armv7-a
@@ -42,6 +42,7 @@
     op TEMPLATE_SHL_LONG armv5te
     op TEMPLATE_SHR_LONG armv5te
     op TEMPLATE_USHR_LONG armv5te
+    op TEMPLATE_THROW_EXCEPTION_COMMON armv5te
 
 op-end
 
diff --git a/vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S b/vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S
index 7b1d6aa..74d6936 100644
--- a/vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S
+++ b/vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S
@@ -1014,6 +1014,18 @@
 .Lsqrt:
     .word   sqrt
 
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON
+dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON:
+/* File: armv5te/TEMPLATE_THROW_EXCEPTION_COMMON.S */
+    /*
+     * Throw an exception from JIT'ed code.
+     * On entry:
+     *    r0    Dalvik PC that raises the exception
+     */
+    b       .LhandleException
+
     .size   dvmCompilerTemplateStart, .-dvmCompilerTemplateStart
 /* File: armv5te/footer.S */
 /*
@@ -1049,15 +1061,19 @@
     str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
     cmp     r1, #0                      @ null?
     str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
+    ldr     r0, [r10, #offStackSaveArea_savedPc] @ reload rPC
     bne     .LhandleException             @ no, handle exception
     bx      r2
 
-/* NOTE - this path can be exercised if the JIT threshold is set to 5 */
+/*
+ * On entry:
+ * r0  Faulting Dalvik PC
+ */
 .LhandleException:
-    ldr     r0, .LdvmMterpCommonExceptionThrown @ PIC way of getting &func
+    ldr     r1, .LdvmMterpCommonExceptionThrown @ PIC way of getting &func
     ldr     rIBASE, .LdvmAsmInstructionStart    @ same as above
-    ldr     rPC, [r10, #offStackSaveArea_savedPc] @ reload rPC
-    mov     pc, r0                  @ branch to dvmMterpCommonExceptionThrown
+    mov     rPC, r0                 @ reload the faulting Dalvik address
+    mov     pc, r1                  @ branch to dvmMterpCommonExceptionThrown
 
     .align  2
 .LdvmAsmInstructionStart:
diff --git a/vm/compiler/template/out/CompilerTemplateAsm-armv5te.S b/vm/compiler/template/out/CompilerTemplateAsm-armv5te.S
index 801c0c7..d2e6f54 100644
--- a/vm/compiler/template/out/CompilerTemplateAsm-armv5te.S
+++ b/vm/compiler/template/out/CompilerTemplateAsm-armv5te.S
@@ -748,6 +748,18 @@
     bx      lr
 
 
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON
+dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON:
+/* File: armv5te/TEMPLATE_THROW_EXCEPTION_COMMON.S */
+    /*
+     * Throw an exception from JIT'ed code.
+     * On entry:
+     *    r0    Dalvik PC that raises the exception
+     */
+    b       .LhandleException
+
     .size   dvmCompilerTemplateStart, .-dvmCompilerTemplateStart
 /* File: armv5te/footer.S */
 /*
@@ -783,15 +795,19 @@
     str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
     cmp     r1, #0                      @ null?
     str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
+    ldr     r0, [r10, #offStackSaveArea_savedPc] @ reload rPC
     bne     .LhandleException             @ no, handle exception
     bx      r2
 
-/* NOTE - this path can be exercised if the JIT threshold is set to 5 */
+/*
+ * On entry:
+ * r0  Faulting Dalvik PC
+ */
 .LhandleException:
-    ldr     r0, .LdvmMterpCommonExceptionThrown @ PIC way of getting &func
+    ldr     r1, .LdvmMterpCommonExceptionThrown @ PIC way of getting &func
     ldr     rIBASE, .LdvmAsmInstructionStart    @ same as above
-    ldr     rPC, [r10, #offStackSaveArea_savedPc] @ reload rPC
-    mov     pc, r0                  @ branch to dvmMterpCommonExceptionThrown
+    mov     rPC, r0                 @ reload the faulting Dalvik address
+    mov     pc, r1                  @ branch to dvmMterpCommonExceptionThrown
 
     .align  2
 .LdvmAsmInstructionStart:
diff --git a/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S b/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S
index 854871b..4ed5ea1 100644
--- a/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S
+++ b/vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S
@@ -1014,6 +1014,18 @@
 .Lsqrt:
     .word   sqrt
 
+/* ------------------------------ */
+    .balign 4
+    .global dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON
+dvmCompiler_TEMPLATE_THROW_EXCEPTION_COMMON:
+/* File: armv5te/TEMPLATE_THROW_EXCEPTION_COMMON.S */
+    /*
+     * Throw an exception from JIT'ed code.
+     * On entry:
+     *    r0    Dalvik PC that raises the exception
+     */
+    b       .LhandleException
+
     .size   dvmCompilerTemplateStart, .-dvmCompilerTemplateStart
 /* File: armv5te/footer.S */
 /*
@@ -1049,15 +1061,19 @@
     str     rFP, [r9, #offThread_curFrame]  @ self->curFrame = fp
     cmp     r1, #0                      @ null?
     str     r0, [r9, #offThread_jniLocal_topCookie] @ new top <- old top
+    ldr     r0, [r10, #offStackSaveArea_savedPc] @ reload rPC
     bne     .LhandleException             @ no, handle exception
     bx      r2
 
-/* NOTE - this path can be exercised if the JIT threshold is set to 5 */
+/*
+ * On entry:
+ * r0  Faulting Dalvik PC
+ */
 .LhandleException:
-    ldr     r0, .LdvmMterpCommonExceptionThrown @ PIC way of getting &func
+    ldr     r1, .LdvmMterpCommonExceptionThrown @ PIC way of getting &func
     ldr     rIBASE, .LdvmAsmInstructionStart    @ same as above
-    ldr     rPC, [r10, #offStackSaveArea_savedPc] @ reload rPC
-    mov     pc, r0                  @ branch to dvmMterpCommonExceptionThrown
+    mov     rPC, r0                 @ reload the faulting Dalvik address
+    mov     pc, r1                  @ branch to dvmMterpCommonExceptionThrown
 
     .align  2
 .LdvmAsmInstructionStart: