OSDN Git Service

Integrate call-graph information into JIT method blacklist.
authorBen Cheng <bccheng@google.com>
Tue, 12 Jan 2010 22:59:30 +0000 (14:59 -0800)
committerBen Cheng <bccheng@google.com>
Wed, 13 Jan 2010 00:22:11 +0000 (16:22 -0800)
The new flag is -Xjitcheckcg which will crawl the stack frame of the
translation requesting thread.

Bug: 2368995

vm/Globals.h
vm/Init.c
vm/compiler/Compiler.c
vm/compiler/Compiler.h
vm/compiler/Frontend.c
vm/compiler/codegen/arm/armv5te-vfp/ArchVariant.c
vm/compiler/codegen/arm/armv5te/ArchVariant.c
vm/compiler/codegen/arm/armv7-a/ArchVariant.c
vm/interp/Jit.c

index d96dbf8..db1cb94 100644 (file)
@@ -765,6 +765,9 @@ struct DvmJitGlobals {
     /* Table to track the overall and trace statistics of hot methods */
     HashTable*  methodStatsTable;
 
+    /* Filter method compilation blacklist with call-graph information */
+    bool checkCallGraph;
+
 #if defined(WITH_SELF_VERIFICATION)
     /* Spin when error is detected, volatile so GDB can reset it */
     volatile bool selfVerificationSpin;
index 86d385b..c65ce65 100644 (file)
--- a/vm/Init.c
+++ b/vm/Init.c
@@ -118,6 +118,7 @@ static void dvmUsage(const char* progName)
     dvmFprintf(stderr, "  -Xjitblocking\n");
     dvmFprintf(stderr, "  -Xjitmethod:signature[,signature]* "
                        "(eg Ljava/lang/String\\;replace)\n");
+    dvmFprintf(stderr, "  -Xjitcheckcg\n");
     dvmFprintf(stderr, "  -Xjitverbose\n");
     dvmFprintf(stderr, "  -Xjitprofile\n");
     dvmFprintf(stderr, "  -Xjitdisableopt\n");
@@ -907,6 +908,10 @@ static int dvmProcessOptions(int argc, const char* const argv[],
           gDvmJit.includeSelectedOp = true;
         } else if (strncmp(argv[i], "-Xincludeselectedmethod", 23) == 0) {
           gDvmJit.includeSelectedMethod = true;
+        } else if (strncmp(argv[i], "-Xjitcheckcg", 12) == 0) {
+          gDvmJit.checkCallGraph = true;
+          /* Need to enable blocking mode due to stack crawling */
+          gDvmJit.blockingMode = true;
         } else if (strncmp(argv[i], "-Xjitverbose", 12) == 0) {
           gDvmJit.printMe = true;
         } else if (strncmp(argv[i], "-Xjitprofile", 12) == 0) {
index 014013d..e7973e3 100644 (file)
@@ -87,6 +87,8 @@ bool dvmCompilerWorkEnqueue(const u2 *pc, WorkOrderKind kind, void* info)
     newOrder->result.discardResult =
         (kind == kWorkOrderTraceDebug || kind == kWorkOrderICPatch) ?
         true : false;
+    newOrder->result.requestingThread = dvmThreadSelf();
+
     gDvmJit.compilerWorkEnqueueIndex++;
     if (gDvmJit.compilerWorkEnqueueIndex == COMPILER_WORK_QUEUE_SIZE)
         gDvmJit.compilerWorkEnqueueIndex = 0;
index c66d562..71eed5d 100644 (file)
@@ -14,6 +14,8 @@
  * limitations under the License.
  */
 
+#include <Thread.h>
+
 #ifndef _DALVIK_VM_COMPILER
 #define _DALVIK_VM_COMPILER
 
@@ -39,6 +41,7 @@ typedef struct JitTranslationInfo {
     void *codeAddress;
     JitInstructionSetType instructionSet;
     bool discardResult;         // Used for debugging divergence and IC patching
+    Thread *requestingThread;   // For debugging purpose
 } JitTranslationInfo;
 
 typedef enum WorkOrderKind {
index 12eb9a7..a4a82c9 100644 (file)
@@ -249,6 +249,36 @@ static CompilerMethodStats *analyzeMethodBody(const Method *method)
 }
 
 /*
+ * Crawl the stack of the thread that requesed compilation to see if any of the
+ * ancestors are on the blacklist.
+ */
+bool filterMethodByCallGraph(Thread *thread, const char *curMethodName)
+{
+    /* Crawl the Dalvik stack frames and compare the method name*/
+    StackSaveArea *ssaPtr = ((StackSaveArea *) thread->curFrame) - 1;
+    while (ssaPtr != ((StackSaveArea *) NULL) - 1) {
+        const Method *method = ssaPtr->method;
+        if (method) {
+            int hashValue = dvmComputeUtf8Hash(method->name);
+            bool found =
+                dvmHashTableLookup(gDvmJit.methodTable, hashValue,
+                               (char *) method->name,
+                               (HashCompareFunc) strcmp, false) !=
+                NULL;
+            if (found) {
+                LOGD("Method %s (--> %s) found on the JIT %s list",
+                     method->name, curMethodName,
+                     gDvmJit.includeSelectedMethod ? "white" : "black");
+                return true;
+            }
+
+        }
+        ssaPtr = ((StackSaveArea *) ssaPtr->prevFrame) - 1;
+    };
+    return false;
+}
+
+/*
  * Main entry point to start trace compilation. Basic blocks are constructed
  * first and they will be passed to the codegen routines to convert Dalvik
  * bytecode into machine code.
@@ -319,6 +349,16 @@ bool dvmCompileTrace(JitTraceDescription *desc, int numMaxInsts,
                                    (char *) desc->method->name,
                                    (HashCompareFunc) strcmp, false) !=
                     NULL;
+
+                /*
+                 * Debug by call-graph is enabled. Check if the debug list
+                 * covers any methods on the VM stack.
+                 */
+                if (methodFound == false && gDvmJit.checkCallGraph == true) {
+                    methodFound =
+                        filterMethodByCallGraph(info->requestingThread,
+                                                desc->method->name);
+                }
             }
         }
 
index 2a8bde1..8b97dc6 100644 (file)
@@ -49,7 +49,6 @@ bool dvmCompilerArchVariantInit(void)
 #undef JIT_TEMPLATE
 
     /* Target-specific configuration */
-    gDvmJit.blockingMode = false;
     gDvmJit.jitTableSize = 1 << 9; // 512
     gDvmJit.jitTableMask = gDvmJit.jitTableSize - 1;
     gDvmJit.threshold = 200;
index 6dff45a..a6d9c88 100644 (file)
@@ -49,7 +49,6 @@ bool dvmCompilerArchVariantInit(void)
 #undef JIT_TEMPLATE
 
     /* Target-specific configuration */
-    gDvmJit.blockingMode = false;
     gDvmJit.jitTableSize = 1 << 9; // 512
     gDvmJit.jitTableMask = gDvmJit.jitTableSize - 1;
     gDvmJit.threshold = 200;
index 0e4cc2b..326bec7 100644 (file)
@@ -45,7 +45,6 @@ bool dvmCompilerArchVariantInit(void)
 #undef JIT_TEMPLATE
 
     /* Target-specific configuration */
-    gDvmJit.blockingMode = false;
     gDvmJit.jitTableSize = 1 << 12; // 4096
     gDvmJit.jitTableMask = gDvmJit.jitTableSize - 1;
     gDvmJit.threshold = 40;
index e327511..2d35e51 100644 (file)
@@ -781,7 +781,7 @@ JitEntry *dvmFindJitEntry(const u2* pc)
 void* dvmJitGetCodeAddr(const u2* dPC)
 {
     int idx = dvmJitHash(dPC);
-    u2* npc = gDvmJit.pJitEntryTable[idx].dPC;
+    const u2* npc = gDvmJit.pJitEntryTable[idx].dPC;
 
     if (npc != NULL) {
         if (npc == dPC) {