OSDN Git Service

Fix for the JIT blocking mode plus some code cleanup.
authorBen Cheng <bccheng@android.com>
Wed, 24 Mar 2010 22:24:19 +0000 (15:24 -0700)
committerBen Cheng <bccheng@android.com>
Wed, 24 Mar 2010 22:33:26 +0000 (15:33 -0700)
Bug: 2517606
Change-Id: I2b5aa92ceaf23d484329330ae20de5966704280b

13 files changed:
vm/compiler/Compiler.c
vm/compiler/CompilerIR.h
vm/compiler/codegen/arm/CodegenDriver.c
vm/compiler/codegen/arm/armv5te-vfp/ArchVariant.c
vm/compiler/codegen/arm/armv5te/ArchVariant.c
vm/compiler/codegen/arm/armv7-a-neon/ArchVariant.c
vm/compiler/codegen/arm/armv7-a/ArchVariant.c
vm/compiler/template/armv5te/footer.S
vm/compiler/template/out/CompilerTemplateAsm-armv5te-vfp.S
vm/compiler/template/out/CompilerTemplateAsm-armv5te.S
vm/compiler/template/out/CompilerTemplateAsm-armv7-a-neon.S
vm/compiler/template/out/CompilerTemplateAsm-armv7-a.S
vm/interp/Jit.c

index 2256c47..efbe0a5 100644 (file)
@@ -112,12 +112,14 @@ unlockAndExit:
     return result;
 }
 
-/* Block until queue length is 0 */
+/* Block until the queue length is 0, or there is a pending suspend request */
 void dvmCompilerDrainQueue(void)
 {
-    int oldStatus = dvmChangeStatus(NULL, THREAD_VMWAIT);
+    Thread *self = dvmThreadSelf();
+
     dvmLockMutex(&gDvmJit.compilerLock);
-    while (workQueueLength() != 0 && !gDvmJit.haltCompilerThread) {
+    while (workQueueLength() != 0 && !gDvmJit.haltCompilerThread &&
+           self->suspendCount == 0) {
         /*
          * Use timed wait here - more than one mutator threads may be blocked
          * but the compiler thread will only signal once when the queue is
@@ -127,7 +129,6 @@ void dvmCompilerDrainQueue(void)
         dvmRelativeCondWait(&gDvmJit.compilerQueueEmpty, &gDvmJit.compilerLock,                             1000, 0);
     }
     dvmUnlockMutex(&gDvmJit.compilerLock);
-    dvmChangeStatus(NULL, oldStatus);
 }
 
 bool dvmCompilerSetupCodeCache(void)
@@ -577,8 +578,15 @@ static void *compilerThreadStart(void *arg)
                 /*
                  * Check whether there is a suspend request on me.  This
                  * is necessary to allow a clean shutdown.
+                 *
+                 * However, in the blocking stress testing mode, let the
+                 * compiler thread continue doing compilations to unblock
+                 * other requesting threads. This may occasionally cause
+                 * shutdown from proceeding cleanly in the standalone invocation
+                 * of the vm but this should be acceptable.
                  */
-                dvmCheckSuspendPending(NULL);
+                if (!gDvmJit.blockingMode)
+                    dvmCheckSuspendPending(NULL);
                 /* Is JitTable filling up? */
                 if (gDvmJit.jitTableEntriesUsed >
                     (gDvmJit.jitTableSize - gDvmJit.jitTableSize/4)) {
index 00a45f9..2bf243d 100644 (file)
@@ -184,6 +184,12 @@ typedef struct CompilationUnit {
     const u2 *switchOverflowPad;
 } CompilationUnit;
 
+#if defined(WITH_SELF_VERIFICATION)
+#define HEAP_ACCESS_SHADOW(_state) cUnit->heapMemOp = _state
+#else
+#define HEAP_ACCESS_SHADOW(_state)
+#endif
+
 BasicBlock *dvmCompilerNewBB(BBType blockType);
 
 void dvmCompilerAppendMIR(BasicBlock *bb, MIR *mir);
index 79a9fb3..11d8268 100644 (file)
@@ -275,13 +275,11 @@ static void genIGetWide(CompilationUnit *cUnit, MIR *mir, int fieldOffset)
                  NULL);/* null object? */
     opRegRegImm(cUnit, kOpAdd, regPtr, rlObj.lowReg, fieldOffset);
     rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
-#if defined(WITH_SELF_VERIFICATION)
-    cUnit->heapMemOp = true;
-#endif
+
+    HEAP_ACCESS_SHADOW(true);
     loadPair(cUnit, regPtr, rlResult.lowReg, rlResult.highReg);
-#if defined(WITH_SELF_VERIFICATION)
-    cUnit->heapMemOp = false;
-#endif
+    HEAP_ACCESS_SHADOW(false);
+
     dvmCompilerFreeTemp(cUnit, regPtr);
     storeValueWide(cUnit, rlDest, rlResult);
 }
@@ -299,13 +297,11 @@ static void genIPutWide(CompilationUnit *cUnit, MIR *mir, int fieldOffset)
                  NULL);/* null object? */
     regPtr = dvmCompilerAllocTemp(cUnit);
     opRegRegImm(cUnit, kOpAdd, regPtr, rlObj.lowReg, fieldOffset);
-#if defined(WITH_SELF_VERIFICATION)
-    cUnit->heapMemOp = true;
-#endif
+
+    HEAP_ACCESS_SHADOW(true);
     storePair(cUnit, regPtr, rlSrc.lowReg, rlSrc.highReg);
-#if defined(WITH_SELF_VERIFICATION)
-    cUnit->heapMemOp = false;
-#endif
+    HEAP_ACCESS_SHADOW(false);
+
     dvmCompilerFreeTemp(cUnit, regPtr);
 }
 
@@ -325,14 +321,12 @@ static void genIGet(CompilationUnit *cUnit, MIR *mir, OpSize size,
     rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
     genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
                  NULL);/* null object? */
-#if defined(WITH_SELF_VERIFICATION)
-    cUnit->heapMemOp = true;
-#endif
+
+    HEAP_ACCESS_SHADOW(true);
     loadBaseDisp(cUnit, mir, rlObj.lowReg, fieldOffset, rlResult.lowReg,
                  size, rlObj.sRegLow);
-#if defined(WITH_SELF_VERIFICATION)
-    cUnit->heapMemOp = false;
-#endif
+    HEAP_ACCESS_SHADOW(false);
+
     storeValue(cUnit, rlDest, rlResult);
 }
 
@@ -351,13 +345,10 @@ static void genIPut(CompilationUnit *cUnit, MIR *mir, OpSize size,
     int regPtr;
     genNullCheck(cUnit, rlObj.sRegLow, rlObj.lowReg, mir->offset,
                  NULL);/* null object? */
-#if defined(WITH_SELF_VERIFICATION)
-    cUnit->heapMemOp = true;
-#endif
+
+    HEAP_ACCESS_SHADOW(true);
     storeBaseDisp(cUnit, rlObj.lowReg, fieldOffset, rlSrc.lowReg, size);
-#if defined(WITH_SELF_VERIFICATION)
-    cUnit->heapMemOp = false;
-#endif
+    HEAP_ACCESS_SHADOW(false);
 }
 
 
@@ -408,25 +399,21 @@ static void genArrayGet(CompilationUnit *cUnit, MIR *mir, OpSize size,
             opRegReg(cUnit, kOpAdd, regPtr, rlIndex.lowReg);
         }
         rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
-#if defined(WITH_SELF_VERIFICATION)
-        cUnit->heapMemOp = true;
-#endif
+
+        HEAP_ACCESS_SHADOW(true);
         loadPair(cUnit, regPtr, rlResult.lowReg, rlResult.highReg);
-#if defined(WITH_SELF_VERIFICATION)
-        cUnit->heapMemOp = false;
-#endif
+        HEAP_ACCESS_SHADOW(false);
+
         dvmCompilerFreeTemp(cUnit, regPtr);
         storeValueWide(cUnit, rlDest, rlResult);
     } else {
         rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
-#if defined(WITH_SELF_VERIFICATION)
-        cUnit->heapMemOp = true;
-#endif
+
+        HEAP_ACCESS_SHADOW(true);
         loadBaseIndexed(cUnit, regPtr, rlIndex.lowReg, rlResult.lowReg,
                         scale, size);
-#if defined(WITH_SELF_VERIFICATION)
-        cUnit->heapMemOp = false;
-#endif
+        HEAP_ACCESS_SHADOW(false);
+
         dvmCompilerFreeTemp(cUnit, regPtr);
         storeValue(cUnit, rlDest, rlResult);
     }
@@ -489,24 +476,19 @@ static void genArrayPut(CompilationUnit *cUnit, MIR *mir, OpSize size,
             opRegReg(cUnit, kOpAdd, regPtr, rlIndex.lowReg);
         }
         rlSrc = loadValueWide(cUnit, rlSrc, kAnyReg);
-#if defined(WITH_SELF_VERIFICATION)
-        cUnit->heapMemOp = true;
-#endif
+
+        HEAP_ACCESS_SHADOW(true);
         storePair(cUnit, regPtr, rlSrc.lowReg, rlSrc.highReg);
-#if defined(WITH_SELF_VERIFICATION)
-        cUnit->heapMemOp = false;
-#endif
+        HEAP_ACCESS_SHADOW(false);
+
         dvmCompilerFreeTemp(cUnit, regPtr);
     } else {
         rlSrc = loadValue(cUnit, rlSrc, kAnyReg);
-#if defined(WITH_SELF_VERIFICATION)
-        cUnit->heapMemOp = true;
-#endif
+
+        HEAP_ACCESS_SHADOW(true);
         storeBaseIndexed(cUnit, regPtr, rlIndex.lowReg, rlSrc.lowReg,
                          scale, size);
-#if defined(WITH_SELF_VERIFICATION)
-        cUnit->heapMemOp = false;
-#endif
+        HEAP_ACCESS_SHADOW(false);
     }
 }
 
@@ -585,14 +567,10 @@ static void genArrayObjectPut(CompilationUnit *cUnit, MIR *mir,
     target->defMask = ENCODE_ALL;
     branchOver->generic.target = (LIR *) target;
 
-#if defined(WITH_SELF_VERIFICATION)
-    cUnit->heapMemOp = true;
-#endif
+    HEAP_ACCESS_SHADOW(true);
     storeBaseIndexed(cUnit, regPtr, regIndex, r0,
                      scale, kWord);
-#if defined(WITH_SELF_VERIFICATION)
-    cUnit->heapMemOp = false;
-#endif
+    HEAP_ACCESS_SHADOW(false);
 }
 
 static bool genShiftOpLong(CompilationUnit *cUnit, MIR *mir,
@@ -1529,13 +1507,11 @@ static bool handleFmt21c_Fmt31c(CompilationUnit *cUnit, MIR *mir)
             rlDest = dvmCompilerGetDest(cUnit, mir, 0);
             rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
             loadConstant(cUnit, tReg,  (int) fieldPtr + valOffset);
-#if defined(WITH_SELF_VERIFICATION)
-            cUnit->heapMemOp = true;
-#endif
+
+            HEAP_ACCESS_SHADOW(true);
             loadWordDisp(cUnit, tReg, 0, rlResult.lowReg);
-#if defined(WITH_SELF_VERIFICATION)
-            cUnit->heapMemOp = false;
-#endif
+            HEAP_ACCESS_SHADOW(false);
+
             storeValue(cUnit, rlDest, rlResult);
             break;
         }
@@ -1548,13 +1524,11 @@ static bool handleFmt21c_Fmt31c(CompilationUnit *cUnit, MIR *mir)
             rlDest = dvmCompilerGetDestWide(cUnit, mir, 0, 1);
             rlResult = dvmCompilerEvalLoc(cUnit, rlDest, kAnyReg, true);
             loadConstant(cUnit, tReg,  (int) fieldPtr + valOffset);
-#if defined(WITH_SELF_VERIFICATION)
-            cUnit->heapMemOp = true;
-#endif
+
+            HEAP_ACCESS_SHADOW(true);
             loadPair(cUnit, tReg, rlResult.lowReg, rlResult.highReg);
-#if defined(WITH_SELF_VERIFICATION)
-            cUnit->heapMemOp = false;
-#endif
+            HEAP_ACCESS_SHADOW(false);
+
             storeValueWide(cUnit, rlDest, rlResult);
             break;
         }
@@ -1573,13 +1547,11 @@ static bool handleFmt21c_Fmt31c(CompilationUnit *cUnit, MIR *mir)
             rlSrc = dvmCompilerGetSrc(cUnit, mir, 0);
             rlSrc = loadValue(cUnit, rlSrc, kAnyReg);
             loadConstant(cUnit, tReg,  (int) fieldPtr + valOffset);
-#if defined(WITH_SELF_VERIFICATION)
-            cUnit->heapMemOp = true;
-#endif
+
+            HEAP_ACCESS_SHADOW(true);
             storeWordDisp(cUnit, tReg, 0 ,rlSrc.lowReg);
-#if defined(WITH_SELF_VERIFICATION)
-            cUnit->heapMemOp = false;
-#endif
+            HEAP_ACCESS_SHADOW(false);
+
             break;
         }
         case OP_SPUT_WIDE: {
@@ -1592,13 +1564,10 @@ static bool handleFmt21c_Fmt31c(CompilationUnit *cUnit, MIR *mir)
             rlSrc = dvmCompilerGetSrcWide(cUnit, mir, 0, 1);
             rlSrc = loadValueWide(cUnit, rlSrc, kAnyReg);
             loadConstant(cUnit, tReg,  (int) fieldPtr + valOffset);
-#if defined(WITH_SELF_VERIFICATION)
-            cUnit->heapMemOp = true;
-#endif
+
+            HEAP_ACCESS_SHADOW(true);
             storePair(cUnit, tReg, rlSrc.lowReg, rlSrc.highReg);
-#if defined(WITH_SELF_VERIFICATION)
-            cUnit->heapMemOp = false;
-#endif
+            HEAP_ACCESS_SHADOW(false);
             break;
         }
         case OP_NEW_INSTANCE: {
@@ -1657,7 +1626,7 @@ static bool handleFmt21c_Fmt31c(CompilationUnit *cUnit, MIR *mir)
              * so that we can tell if it happens frequently.
              */
             if (classPtr == NULL) {
-                 LOGD("null clazz in OP_CHECK_CAST, single-stepping");
+                 LOGVV("null clazz in OP_CHECK_CAST, single-stepping");
                  genInterpSingleStep(cUnit, mir);
                  return false;
             }
@@ -3251,9 +3220,14 @@ static bool handleFmt51l(CompilationUnit *cUnit, MIR *mir)
 static void handleNormalChainingCell(CompilationUnit *cUnit,
                                      unsigned int offset)
 {
-    loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
-                 jitToInterpEntries.dvmJitToInterpNormal), r0);
-    opReg(cUnit, kOpBlx, r0);
+    /*
+     * Use raw instruction constructors to guarantee that the generated
+     * instructions fit the predefined cell size.
+     */
+    newLIR3(cUnit, kThumbLdrRRI5, r0, rGLUE,
+            offsetof(InterpState,
+                     jitToInterpEntries.dvmJitToInterpNormal) >> 2);
+    newLIR1(cUnit, kThumbBlxR, r0);
     addWordData(cUnit, (int) (cUnit->method->insns + offset), true);
 }
 
@@ -3264,9 +3238,14 @@ static void handleNormalChainingCell(CompilationUnit *cUnit,
 static void handleHotChainingCell(CompilationUnit *cUnit,
                                   unsigned int offset)
 {
-    loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
-                 jitToInterpEntries.dvmJitToInterpTraceSelect), r0);
-    opReg(cUnit, kOpBlx, r0);
+    /*
+     * Use raw instruction constructors to guarantee that the generated
+     * instructions fit the predefined cell size.
+     */
+    newLIR3(cUnit, kThumbLdrRRI5, r0, rGLUE,
+            offsetof(InterpState,
+                     jitToInterpEntries.dvmJitToInterpTraceSelect) >> 2);
+    newLIR1(cUnit, kThumbBlxR, r0);
     addWordData(cUnit, (int) (cUnit->method->insns + offset), true);
 }
 
@@ -3275,6 +3254,10 @@ static void handleHotChainingCell(CompilationUnit *cUnit,
 static void handleBackwardBranchChainingCell(CompilationUnit *cUnit,
                                              unsigned int offset)
 {
+    /*
+     * Use raw instruction constructors to guarantee that the generated
+     * instructions fit the predefined cell size.
+     */
 #if defined(WITH_SELF_VERIFICATION)
     newLIR3(cUnit, kThumbLdrRRI5, r0, rGLUE,
         offsetof(InterpState,
@@ -3292,9 +3275,14 @@ static void handleBackwardBranchChainingCell(CompilationUnit *cUnit,
 static void handleInvokeSingletonChainingCell(CompilationUnit *cUnit,
                                               const Method *callee)
 {
-    loadWordDisp(cUnit, rGLUE, offsetof(InterpState,
-                 jitToInterpEntries.dvmJitToInterpTraceSelect), r0);
-    opReg(cUnit, kOpBlx, r0);
+    /*
+     * Use raw instruction constructors to guarantee that the generated
+     * instructions fit the predefined cell size.
+     */
+    newLIR3(cUnit, kThumbLdrRRI5, r0, rGLUE,
+            offsetof(InterpState,
+                     jitToInterpEntries.dvmJitToInterpTraceSelect) >> 2);
+    newLIR1(cUnit, kThumbBlxR, r0);
     addWordData(cUnit, (int) (callee->insns), true);
 }
 
index aa343aa..7f9fa3b 100644 (file)
@@ -57,6 +57,7 @@ bool dvmCompilerArchVariantInit(void)
 #if defined(WITH_SELF_VERIFICATION)
     /* Force into blocking mode */
     gDvmJit.blockingMode = true;
+    gDvm.nativeDebuggerActive = true;
 #endif
 
     /* Codegen-specific assumptions */
@@ -70,11 +71,11 @@ bool dvmCompilerArchVariantInit(void)
     assert(sizeof(StackSaveArea) < 236);
 
     /*
-     * EA is calculated by doing "Rn + imm5 << 2", and there are 5 entry points
-     * that codegen may access, make sure that the offset from the top of the
-     * struct is less than 108.
+     * EA is calculated by doing "Rn + imm5 << 2", make sure that the last
+     * offset from the struct is less than 128.
      */
-    assert(offsetof(InterpState, jitToInterpEntries) < 108);
+    assert((offsetof(InterpState, jitToInterpEntries) +
+            sizeof(struct JitToInterpEntries)) <= 128);
     return true;
 }
 
index d33debe..e018ea1 100644 (file)
@@ -57,6 +57,7 @@ bool dvmCompilerArchVariantInit(void)
 #if defined(WITH_SELF_VERIFICATION)
     /* Force into blocking mode */
     gDvmJit.blockingMode = true;
+    gDvm.nativeDebuggerActive = true;
 #endif
 
     /* Codegen-specific assumptions */
@@ -70,11 +71,11 @@ bool dvmCompilerArchVariantInit(void)
     assert(sizeof(StackSaveArea) < 236);
 
     /*
-     * EA is calculated by doing "Rn + imm5 << 2", and there are 5 entry points
-     * that codegen may access, make sure that the offset from the top of the
-     * struct is less than 108.
+     * EA is calculated by doing "Rn + imm5 << 2", make sure that the last
+     * offset from the struct is less than 128.
      */
-    assert(offsetof(InterpState, jitToInterpEntries) < 108);
+    assert((offsetof(InterpState, jitToInterpEntries) +
+            sizeof(struct JitToInterpEntries)) <= 128);
     return true;
 }
 
index fe2b1d4..5a14774 100644 (file)
@@ -52,6 +52,7 @@ bool dvmCompilerArchVariantInit(void)
 #if defined(WITH_SELF_VERIFICATION)
     /* Force into blocking */
     gDvmJit.blockingMode = true;
+    gDvm.nativeDebuggerActive = true;
 #endif
 
     /* Codegen-specific assumptions */
@@ -65,11 +66,11 @@ bool dvmCompilerArchVariantInit(void)
     assert(sizeof(StackSaveArea) < 236);
 
     /*
-     * EA is calculated by doing "Rn + imm5 << 2", and there are 5 entry points
-     * that codegen may access, make sure that the offset from the top of the
-     * struct is less than 108.
+     * EA is calculated by doing "Rn + imm5 << 2", make sure that the last
+     * offset from the struct is less than 128.
      */
-    assert(offsetof(InterpState, jitToInterpEntries) < 108);
+    assert((offsetof(InterpState, jitToInterpEntries) +
+            sizeof(struct JitToInterpEntries)) <= 128);
     return true;
 }
 
index fe2b1d4..5a14774 100644 (file)
@@ -52,6 +52,7 @@ bool dvmCompilerArchVariantInit(void)
 #if defined(WITH_SELF_VERIFICATION)
     /* Force into blocking */
     gDvmJit.blockingMode = true;
+    gDvm.nativeDebuggerActive = true;
 #endif
 
     /* Codegen-specific assumptions */
@@ -65,11 +66,11 @@ bool dvmCompilerArchVariantInit(void)
     assert(sizeof(StackSaveArea) < 236);
 
     /*
-     * EA is calculated by doing "Rn + imm5 << 2", and there are 5 entry points
-     * that codegen may access, make sure that the offset from the top of the
-     * struct is less than 108.
+     * EA is calculated by doing "Rn + imm5 << 2", make sure that the last
+     * offset from the struct is less than 128.
      */
-    assert(offsetof(InterpState, jitToInterpEntries) < 108);
+    assert((offsetof(InterpState, jitToInterpEntries) +
+            sizeof(struct JitToInterpEntries)) <= 128);
     return true;
 }
 
index 8d1c8c2..b93eee3 100644 (file)
  * r0  Faulting Dalvik PC
  */
 .LhandleException:
+#if defined(WITH_SELF_VERIFICATION)
+    ldr     pc, .LdeadFood @ should not see this under self-verification mode
+.LdeadFood:
+    .word   0xdeadf00d
+#endif
     ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
     mov     r2, #0
     str     r2, [r3, #offThread_inJitCodeCache] @ in interpreter land
index 9c1e788..d8a2784 100644 (file)
@@ -1501,6 +1501,11 @@ dvmCompiler_TEMPLATE_MONITOR_ENTER_DEBUG:
  * r0  Faulting Dalvik PC
  */
 .LhandleException:
+#if defined(WITH_SELF_VERIFICATION)
+    ldr     pc, .LdeadFood @ should not see this under self-verification mode
+.LdeadFood:
+    .word   0xdeadf00d
+#endif
     ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
     mov     r2, #0
     str     r2, [r3, #offThread_inJitCodeCache] @ in interpreter land
index e73d940..eab49cf 100644 (file)
@@ -1229,6 +1229,11 @@ dvmCompiler_TEMPLATE_MONITOR_ENTER_DEBUG:
  * r0  Faulting Dalvik PC
  */
 .LhandleException:
+#if defined(WITH_SELF_VERIFICATION)
+    ldr     pc, .LdeadFood @ should not see this under self-verification mode
+.LdeadFood:
+    .word   0xdeadf00d
+#endif
     ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
     mov     r2, #0
     str     r2, [r3, #offThread_inJitCodeCache] @ in interpreter land
index 51a5004..cb00858 100644 (file)
@@ -1501,6 +1501,11 @@ dvmCompiler_TEMPLATE_MONITOR_ENTER_DEBUG:
  * r0  Faulting Dalvik PC
  */
 .LhandleException:
+#if defined(WITH_SELF_VERIFICATION)
+    ldr     pc, .LdeadFood @ should not see this under self-verification mode
+.LdeadFood:
+    .word   0xdeadf00d
+#endif
     ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
     mov     r2, #0
     str     r2, [r3, #offThread_inJitCodeCache] @ in interpreter land
index 737ea5f..cf6fff9 100644 (file)
@@ -1501,6 +1501,11 @@ dvmCompiler_TEMPLATE_MONITOR_ENTER_DEBUG:
  * r0  Faulting Dalvik PC
  */
 .LhandleException:
+#if defined(WITH_SELF_VERIFICATION)
+    ldr     pc, .LdeadFood @ should not see this under self-verification mode
+.LdeadFood:
+    .word   0xdeadf00d
+#endif
     ldr     r3, [rGLUE, #offGlue_self]  @ r3<- glue->self
     mov     r2, #0
     str     r2, [r3, #offThread_inJitCodeCache] @ in interpreter land
index 1d7961e..1be8096 100644 (file)
@@ -64,8 +64,8 @@ void* dvmSelfVerificationSaveState(const u2* pc, const void* fp,
 {
     Thread *self = dvmThreadSelf();
     ShadowSpace *shadowSpace = self->shadowSpace;
-    int preBytes = interpState->method->outsSize*4 + sizeof(StackSaveArea);
-    int postBytes = interpState->method->registersSize*4;
+    unsigned preBytes = interpState->method->outsSize*4 + sizeof(StackSaveArea);
+    unsigned postBytes = interpState->method->registersSize*4;
 
     //LOGD("### selfVerificationSaveState(%d) pc: 0x%x fp: 0x%x",
     //    self->threadId, (int)pc, (int)fp);
@@ -79,11 +79,11 @@ void* dvmSelfVerificationSaveState(const u2* pc, const void* fp,
     shadowSpace->selfVerificationState = kSVSStart;
 
     // Dynamically grow shadow register space if necessary
-    while (preBytes + postBytes > shadowSpace->registerSpaceSize) {
-        shadowSpace->registerSpaceSize *= 2;
+    if (preBytes + postBytes > shadowSpace->registerSpaceSize * sizeof(u4)) {
         free(shadowSpace->registerSpace);
+        shadowSpace->registerSpaceSize = (preBytes + postBytes) / sizeof(u4);
         shadowSpace->registerSpace =
-            (int*) calloc(shadowSpace->registerSpaceSize, sizeof(int));
+            (int*) calloc(shadowSpace->registerSpaceSize, sizeof(u4));
     }
 
     // Remember original state
@@ -145,7 +145,8 @@ void* dvmSelfVerificationRestoreState(const u2* pc, const void* fp,
     }
 
     // Special case when punting after a single instruction
-    if (exitPoint == kSVSPunt && pc == shadowSpace->startPC) {
+    if ((exitPoint == kSVSPunt || exitPoint == kSVSSingleStep) &&
+        pc == shadowSpace->startPC) {
         shadowSpace->selfVerificationState = kSVSIdle;
     } else {
         shadowSpace->selfVerificationState = exitPoint;
@@ -257,8 +258,7 @@ static bool selfVerificationDebugInterp(const u2* pc, Thread* self)
     }
 
     /* Check that the current pc is the end of the trace */
-    if ((state == kSVSSingleStep || state == kSVSDebugInterp) &&
-        pc == shadowSpace->endPC) {
+    if (state == kSVSDebugInterp && pc == shadowSpace->endPC) {
 
         shadowSpace->selfVerificationState = kSVSIdle;
 
@@ -473,9 +473,16 @@ static bool selfVerificationPuntOps(DecodedInstruction *decInsn)
 {
     OpCode op = decInsn->opCode;
     int flags =  dexGetInstrFlags(gDvm.instrFlags, op);
+    /*
+     * All opcodes that can throw exceptions and use the
+     * TEMPLATE_THROW_EXCEPTION_COMMON template should be excluded in the trace
+     * under self-verification mode.
+     */
     return (op == OP_MONITOR_ENTER || op == OP_MONITOR_EXIT ||
             op == OP_NEW_INSTANCE || op == OP_NEW_ARRAY ||
             op == OP_CHECK_CAST || op == OP_MOVE_EXCEPTION ||
+            op == OP_FILL_ARRAY_DATA || op == OP_EXECUTE_INLINE ||
+            op == OP_EXECUTE_INLINE_RANGE ||
             (flags & kInstrInvoke));
 }
 #endif