Change the tread state before acquiring the code cache lock.

Fix a deadlock situation.
Bug: 4192964

Change-Id: I27f869d90d58f67e675a65444ebed6fdf2a5f518
diff --git a/vm/compiler/codegen/arm/Assemble.c b/vm/compiler/codegen/arm/Assemble.c
index dfc68b6..4f2c10a 100644
--- a/vm/compiler/codegen/arm/Assemble.c
+++ b/vm/compiler/codegen/arm/Assemble.c
@@ -2272,13 +2272,25 @@
     int numClassPointers = *(int *)classPointerP++;
     intptr_t *startClassPointerP = classPointerP;
 
-    UNPROTECT_CODE_CACHE(startClassPointerP,
-                         numClassPointers * sizeof(intptr_t));
     /*
      * Change the thread state to VM_RUNNING so that GC won't be happening
-     * when the assembler looks up the class pointers.
+     * when the assembler looks up the class pointers. May suspend the current
+     * thread if there is a pending request before the state is actually
+     * changed to RUNNING.
      */
     dvmChangeStatus(gDvmJit.compilerThread, THREAD_RUNNING);
+
+    /*
+     * Unprotecting the code cache will need to acquire the code cache
+     * protection lock first. Doing so after the state change may increase the
+     * time spent in the RUNNING state (which may delay the next GC request
+     * should there be contention on codeCacheProtectionLock). In practice
+     * this is probably not going to happen often since a GC is just served.
+     * More importantly, acquiring the lock before the state change will
+     * cause deadlock (b/4192964).
+     */
+    UNPROTECT_CODE_CACHE(startClassPointerP,
+                         numClassPointers * sizeof(intptr_t));
 #if defined(WITH_JIT_TUNING)
     u8 startTime = dvmGetRelativeTimeUsec();
 #endif
@@ -2305,12 +2317,12 @@
         gDvmJit.maxCompilerThreadBlockGCTime = blockTime;
     gDvmJit.numCompilerThreadBlockGC++;
 #endif
-    /* Change the thread state back to VMWAIT */
-    dvmChangeStatus(gDvmJit.compilerThread, THREAD_VMWAIT);
-
     UPDATE_CODE_CACHE_PATCHES();
 
     PROTECT_CODE_CACHE(startClassPointerP, numClassPointers * sizeof(intptr_t));
+
+    /* Change the thread state back to VMWAIT */
+    dvmChangeStatus(gDvmJit.compilerThread, THREAD_VMWAIT);
 }
 
 #if defined(WITH_SELF_VERIFICATION)