Remove the write permission for the JIT code cache when not needed

To support the feature, redesigned the predicted chaining mechanism so that the
profile count is shared globally in InterpState.

Bug: 2690371
Change-Id: Ifed427e8b1fa4f6c670f19e0761e45e2d4afdbb6
diff --git a/vm/compiler/Compiler.c b/vm/compiler/Compiler.c
index 0f60f20..9b32703 100644
--- a/vm/compiler/Compiler.c
+++ b/vm/compiler/Compiler.c
@@ -153,6 +153,8 @@
         return false;
     }
 
+    gDvmJit.pageSizeMask = getpagesize() - 1;
+
     /* This can be found through "dalvik-jit-code-cache" in /proc/<pid>/maps */
     // LOGD("Code cache starts at %p", gDvmJit.codeCache);
 
@@ -177,6 +179,10 @@
     /* Only flush the part in the code cache that is being used now */
     cacheflush((intptr_t) gDvmJit.codeCache,
                (intptr_t) gDvmJit.codeCache + templateSize, 0);
+
+    mprotect(gDvmJit.codeCache, gDvmJit.codeCacheSize,
+             PROTECT_CODE_CACHE_ATTRS);
+
     return true;
 }
 
@@ -261,6 +267,7 @@
     /* Reset the JitEntry table contents to the initial unpopulated state */
     dvmJitResetTable();
 
+    UNPROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed);
     /*
      * Wipe out the code cache content to force immediate crashes if
      * stale JIT'ed code is invoked.
@@ -271,6 +278,8 @@
     cacheflush((intptr_t) gDvmJit.codeCache,
                (intptr_t) gDvmJit.codeCache + gDvmJit.codeCacheByteUsed, 0);
 
+    PROTECT_CODE_CACHE(gDvmJit.codeCache, gDvmJit.codeCacheByteUsed);
+
     /* Reset the current mark of used bytes to the end of template code */
     gDvmJit.codeCacheByteUsed = gDvmJit.templateSize;
     gDvmJit.numCompilations = 0;
@@ -646,6 +655,7 @@
 
     dvmInitMutex(&gDvmJit.compilerLock);
     dvmInitMutex(&gDvmJit.compilerICPatchLock);
+    dvmInitMutex(&gDvmJit.codeCacheProtectionLock);
     dvmLockMutex(&gDvmJit.compilerLock);
     pthread_cond_init(&gDvmJit.compilerQueueActivity, NULL);
     pthread_cond_init(&gDvmJit.compilerQueueEmpty, NULL);