First phase of restructuring to support THUMB2 & ARM traces
Store some useful info about traces in JitTable entry; some general cleanup
diff --git a/vm/compiler/Compiler.c b/vm/compiler/Compiler.c
index f70b978..203a080 100644
--- a/vm/compiler/Compiler.c
+++ b/vm/compiler/Compiler.c
@@ -118,7 +118,6 @@
             continue;
         } else {
             do {
-                void *compiledCodePtr;
                 CompilerWorkOrder work = workDequeue();
                 dvmUnlockMutex(&gDvmJit.compilerLock);
                 /* Check whether there is a suspend request on me */
@@ -131,10 +130,10 @@
                 if (gDvmJit.haltCompilerThread) {
                     LOGD("Compiler shutdown in progress - discarding request");
                 } else {
-                    compiledCodePtr = dvmCompilerDoWork(&work);
                     /* Compilation is successful */
-                    if (compiledCodePtr) {
-                        dvmJitSetCodeAddr(work.pc, compiledCodePtr);
+                    if (dvmCompilerDoWork(&work)) {
+                        dvmJitSetCodeAddr(work.pc, work.result.codeAddress,
+                                          work.result.instructionSet);
                     }
                 }
                 free(work.info);
diff --git a/vm/compiler/Compiler.h b/vm/compiler/Compiler.h
index 093d48a..2cd112b 100644
--- a/vm/compiler/Compiler.h
+++ b/vm/compiler/Compiler.h
@@ -25,6 +25,21 @@
 #define COMPILER_TRACEE(X)
 #define COMPILER_TRACE_CHAINING(X)
 
+typedef enum JitInstructionSetType {
+    DALVIK_JIT_NONE = 0,
+    DALVIK_JIT_ARM,
+    DALVIK_JIT_THUMB,
+    DALVIK_JIT_THUMB2,
+    DALVIK_JIT_THUMBEE,
+    DALVIK_JIT_X86
+} JitInstructionSetType;
+
+/* Description of a compiled trace. */
+typedef struct JitTranslationInfo {
+    void     *codeAddress;
+    JitInstructionSetType instructionSet;
+} JitTranslationInfo;
+
 typedef enum WorkOrderKind {
     kWorkOrderInvalid = 0,      // Should never see by the backend
     kWorkOrderMethod = 1,       // Work is to compile a whole method
@@ -35,6 +50,7 @@
     const u2* pc;
     WorkOrderKind kind;
     void* info;
+    JitTranslationInfo result;
 } CompilerWorkOrder;
 
 typedef enum JitState {
@@ -98,10 +114,12 @@
 void dvmCompilerShutdown(void);
 bool dvmCompilerWorkEnqueue(const u2* pc, WorkOrderKind kind, void* info);
 void *dvmCheckCodeCache(void *method);
-void *dvmCompileMethod(const Method *method);
-void *dvmCompileTrace(JitTraceDescription *trace, int numMaxInsts);
+bool dvmCompileMethod(const Method *method, JitTranslationInfo *info);
+bool dvmCompileTrace(JitTraceDescription *trace, int numMaxInsts,
+                     JitTranslationInfo *info);
 void dvmCompilerDumpStats(void);
 void dvmCompilerDrainQueue(void);
 void dvmJitUnchainAll(void);
+void dvmCompilerSortAndPrintTraceProfiles(void);
 
 #endif /* _DALVIK_VM_COMPILER */
diff --git a/vm/compiler/CompilerIR.h b/vm/compiler/CompilerIR.h
index 201b0cc..d61d2ee 100644
--- a/vm/compiler/CompilerIR.h
+++ b/vm/compiler/CompilerIR.h
@@ -91,6 +91,7 @@
     LIR *firstChainingLIR[CHAINING_CELL_LAST];
     RegisterScoreboard registerScoreboard;      // Track register dependency
     int optRound;                       // round number to tell an LIR's age
+    JitInstructionSetType instructionSet;
 } CompilationUnit;
 
 BasicBlock *dvmCompilerNewBB(BBType blockType);
diff --git a/vm/compiler/Frontend.c b/vm/compiler/Frontend.c
index 77548d9..c717975 100644
--- a/vm/compiler/Frontend.c
+++ b/vm/compiler/Frontend.c
@@ -239,7 +239,8 @@
  * first and they will be passed to the codegen routines to convert Dalvik
  * bytecode into machine code.
  */
-void *dvmCompileTrace(JitTraceDescription *desc, int numMaxInsts)
+bool dvmCompileTrace(JitTraceDescription *desc, int numMaxInsts,
+                     JitTranslationInfo *info)
 {
     const DexCode *dexCode = dvmGetMethodCode(desc->method);
     const JitTraceRun* currRun = &desc->trace[0];
@@ -523,11 +524,14 @@
         dvmCompilerDumpCompilationUnit(&cUnit);
     }
 
+    /* Set the instruction set to use (NOTE: later components may change it) */
+    cUnit.instructionSet = dvmCompilerInstructionSet(&cUnit);
+
     /* Convert MIR to LIR, etc. */
     dvmCompilerMIR2LIR(&cUnit);
 
     /* Convert LIR into machine code. */
-    dvmCompilerAssembleLIR(&cUnit);
+    dvmCompilerAssembleLIR(&cUnit, info);
 
     if (cUnit.printMe) {
         if (cUnit.halveInstCount) {
@@ -546,17 +550,14 @@
     /* Free the bit vector tracking null-checked registers */
     dvmFreeBitVector(cUnit.registerScoreboard.nullCheckedRegs);
 
-    /*
-     * Things have gone smoothly - publish the starting address of
-     * translation's entry point.
-     */
     if (!cUnit.halveInstCount) {
+    /* Success */
         methodStats->nativeSize += cUnit.totalSize;
-        return cUnit.baseAddr + cUnit.headerSize;
+        return info->codeAddress != NULL;
 
     /* Halve the instruction count and retry again */
     } else {
-        return dvmCompileTrace(desc, cUnit.numInsts / 2);
+        return dvmCompileTrace(desc, cUnit.numInsts / 2, info);
     }
 }
 
@@ -567,7 +568,7 @@
  * TODO: implementation will be revisited when the trace builder can provide
  * whole-method traces.
  */
-void *dvmCompileMethod(const Method *method)
+bool dvmCompileMethod(const Method *method, JitTranslationInfo *info)
 {
     const DexCode *dexCode = dvmGetMethodCode(method);
     const u2 *codePtr = dexCode->insns;
@@ -732,13 +733,16 @@
         }
     }
 
+    /* Set the instruction set to use (NOTE: later components may change it) */
+    cUnit.instructionSet = dvmCompilerInstructionSet(&cUnit);
+
     dvmCompilerMIR2LIR(&cUnit);
 
-    dvmCompilerAssembleLIR(&cUnit);
+    dvmCompilerAssembleLIR(&cUnit, info);
 
     dvmCompilerDumpCompilationUnit(&cUnit);
 
     dvmCompilerArenaReset();
 
-    return cUnit.baseAddr + cUnit.headerSize;
+    return info->codeAddress != NULL;
 }
diff --git a/vm/compiler/codegen/CompilerCodegen.h b/vm/compiler/codegen/CompilerCodegen.h
index 97077b4..c9e6bd6 100644
--- a/vm/compiler/codegen/CompilerCodegen.h
+++ b/vm/compiler/codegen/CompilerCodegen.h
@@ -20,18 +20,23 @@
 #define _DALVIK_VM_COMPILERCODEGEN_H_
 
 /* Work unit is architecture dependent */
-void *dvmCompilerDoWork(CompilerWorkOrder *work);
+bool dvmCompilerDoWork(CompilerWorkOrder *work);
 
 /* Lower middle-level IR to low-level IR */
 void dvmCompilerMIR2LIR(CompilationUnit *cUnit);
 
 /* Assemble LIR into machine code */
-void dvmCompilerAssembleLIR(CompilationUnit *cUnit);
+void dvmCompilerAssembleLIR(CompilationUnit *cUnit, JitTranslationInfo *info);
 
 /* Implemented in the codegen/<target>/ArchUtility.c */
 void dvmCompilerCodegenDump(CompilationUnit *cUnit);
 
 /* Implemented in the codegen/<target>/Assembler.c */
 void* dvmJitChain(void *tgtAddr, u4* branchAddr);
+u4* dvmJitUnchain(void *codeAddr);
+void dvmJitUnchainAll(void);
+
+/* Implemented in codegen/<target>/<target_variant>/ArchVariant.c */
+JitInstructionSetType dvmCompilerInstructionSet(CompilationUnit *cUnit);
 
 #endif /* _DALVIK_VM_COMPILERCODEGEN_H_ */
diff --git a/vm/compiler/codegen/armv5te/ArchUtility.c b/vm/compiler/codegen/armv5te/ArchUtility.c
index e45c572..d7a0ce6 100644
--- a/vm/compiler/codegen/armv5te/ArchUtility.c
+++ b/vm/compiler/codegen/armv5te/ArchUtility.c
@@ -224,7 +224,7 @@
     for (lirInsn = cUnit->wordList; lirInsn; lirInsn = lirInsn->next) {
         armLIR = (Armv5teLIR *) lirInsn;
         LOGD("%p (%04x): .word (0x%x)\n",
-             cUnit->baseAddr + armLIR->generic.offset, armLIR->generic.offset,
+             (char*)cUnit->baseAddr + armLIR->generic.offset, armLIR->generic.offset,
              armLIR->operands[0]);
     }
 }
diff --git a/vm/compiler/codegen/armv5te/Armv5teLIR.h b/vm/compiler/codegen/armv5te/Armv5teLIR.h
index 709b95f..6408038 100644
--- a/vm/compiler/codegen/armv5te/Armv5teLIR.h
+++ b/vm/compiler/codegen/armv5te/Armv5teLIR.h
@@ -179,6 +179,7 @@
     int flags;
     char *name;
     char* fmt;
+    int size;
 } Armv5teEncodingMap;
 
 extern Armv5teEncodingMap EncodingMap[ARMV5TE_LAST];
@@ -194,6 +195,7 @@
     int operands[3];    // [0..2] = [dest, src1, src2]
     bool isNop;         // LIR is optimized away
     int age;            // default is 0, set lazily by the optimizer
+    int size;           // 16-bit unit size (1 for thumb, 1 or 2 for thumb2)
 } Armv5teLIR;
 
 /* Chain cell for predicted method invocation */
diff --git a/vm/compiler/codegen/armv5te/Assemble.c b/vm/compiler/codegen/armv5te/Assemble.c
index 3b3c161..f2f6e8c 100644
--- a/vm/compiler/codegen/armv5te/Assemble.c
+++ b/vm/compiler/codegen/armv5te/Assemble.c
@@ -36,9 +36,9 @@
  * fmt: for pretty-prining
  */
 #define ENCODING_MAP(opcode, skeleton, ds, de, s1s, s1e, s2s, s2e, operands, \
-                     name, fmt) \
+                     name, fmt, size) \
         {skeleton, {{ds, de}, {s1s, s1e}, {s2s, s2e}}, opcode, operands, name, \
-         fmt}
+         fmt, size}
 
 /* Instruction dump string format keys: !pf, where "!" is the start
  * of the key, "p" is which numeric operand to use and "f" is the
@@ -67,224 +67,224 @@
 Armv5teEncodingMap EncodingMap[ARMV5TE_LAST] = {
     ENCODING_MAP(ARMV5TE_16BIT_DATA,    0x0000, 15, 0, -1, -1, -1, -1,
                  IS_UNARY_OP,
-                 "data", "0x!0h(!0d)"),
+                 "data", "0x!0h(!0d)", 1),
     ENCODING_MAP(ARMV5TE_ADC,           0x4140, 2, 0, 5, 3, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
-                 "adc", "r!0d, r!1d"),
+                 "adc", "r!0d, r!1d", 1),
     ENCODING_MAP(ARMV5TE_ADD_RRI3,      0x1c00, 2, 0, 5, 3, 8, 6,
                  IS_TERTIARY_OP | CLOBBER_DEST,
-                 "add", "r!0d, r!1d, #!2d"),
+                 "add", "r!0d, r!1d, #!2d", 1),
     ENCODING_MAP(ARMV5TE_ADD_RI8,       0x3000, 10, 8, 7, 0, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
-                 "add", "r!0d, r!0d, #!1d"),
+                 "add", "r!0d, r!0d, #!1d", 1),
     ENCODING_MAP(ARMV5TE_ADD_RRR,       0x1800, 2, 0, 5, 3, 8, 6,
                  IS_TERTIARY_OP | CLOBBER_DEST,
-                 "add", "r!0d, r!1d, r!2d"),
+                 "add", "r!0d, r!1d, r!2d", 1),
     ENCODING_MAP(ARMV5TE_ADD_RR_LH,     0x4440, 2, 0, 5, 3, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
                  "add",
-                 "r!0d, r!1d"),
+                 "r!0d, r!1d", 1),
     ENCODING_MAP(ARMV5TE_ADD_RR_HL,     0x4480, 2, 0, 5, 3, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
-                 "add", "r!0d, r!1d"),
+                 "add", "r!0d, r!1d", 1),
     ENCODING_MAP(ARMV5TE_ADD_RR_HH,     0x44c0, 2, 0, 5, 3, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
-                 "add", "r!0d, r!1d"),
+                 "add", "r!0d, r!1d", 1),
     ENCODING_MAP(ARMV5TE_ADD_PC_REL,    0xa000, 10, 8, 7, 0, -1, -1,
                  IS_TERTIARY_OP | CLOBBER_DEST,
-                 "add", "r!0d, pc, #!1E"),
+                 "add", "r!0d, pc, #!1E", 1),
     ENCODING_MAP(ARMV5TE_ADD_SP_REL,    0xa800, 10, 8, 7, 0, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
-                 "add", "r!0d, sp, #!1E"),
+                 "add", "r!0d, sp, #!1E", 1),
     ENCODING_MAP(ARMV5TE_ADD_SPI7,      0xb000, 6, 0, -1, -1, -1, -1,
                  IS_UNARY_OP | CLOBBER_DEST,
-                 "add", "sp, #!0d*4"),
+                 "add", "sp, #!0d*4", 1),
     ENCODING_MAP(ARMV5TE_AND_RR,        0x4000, 2, 0, 5, 3, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
-                 "and", "r!0d, r!1d"),
+                 "and", "r!0d, r!1d", 1),
     ENCODING_MAP(ARMV5TE_ASR,           0x1000, 2, 0, 5, 3, 10, 6,
                  IS_TERTIARY_OP | CLOBBER_DEST,
-                 "asr", "r!0d, r!1d, #!2d"),
+                 "asr", "r!0d, r!1d, #!2d", 1),
     ENCODING_MAP(ARMV5TE_ASRV,          0x4100, 2, 0, 5, 3, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
-                 "asr", "r!0d, r!1d"),
+                 "asr", "r!0d, r!1d", 1),
     ENCODING_MAP(ARMV5TE_B_COND,        0xd000, 7, 0, 11, 8, -1, -1,
                  IS_BINARY_OP | IS_BRANCH,
-                 "!1c", "!0t"),
+                 "!1c", "!0t", 1),
     ENCODING_MAP(ARMV5TE_B_UNCOND,      0xe000, 10, 0, -1, -1, -1, -1,
                  NO_OPERAND | IS_BRANCH,
-                 "b", "!0t"),
+                 "b", "!0t", 1),
     ENCODING_MAP(ARMV5TE_BIC,           0x4380, 2, 0, 5, 3, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
-                 "bic", "r!0d, r!1d"),
+                 "bic", "r!0d, r!1d", 1),
     ENCODING_MAP(ARMV5TE_BKPT,          0xbe00, 7, 0, -1, -1, -1, -1,
                  IS_UNARY_OP | IS_BRANCH,
-                 "bkpt", "!0d"),
+                 "bkpt", "!0d", 1),
     ENCODING_MAP(ARMV5TE_BLX_1,         0xf000, 10, 0, -1, -1, -1, -1,
                  IS_BINARY_OP | IS_BRANCH,
-                 "blx_1", "!0u"),
+                 "blx_1", "!0u", 1),
     ENCODING_MAP(ARMV5TE_BLX_2,         0xe800, 10, 0, -1, -1, -1, -1,
                  IS_BINARY_OP | IS_BRANCH,
-                 "blx_2", "!0v"),
+                 "blx_2", "!0v", 1),
     ENCODING_MAP(ARMV5TE_BL_1,          0xf000, 10, 0, -1, -1, -1, -1,
                  IS_UNARY_OP | IS_BRANCH,
-                 "bl_1", "!0u"),
+                 "bl_1", "!0u", 1),
     ENCODING_MAP(ARMV5TE_BL_2,          0xf800, 10, 0, -1, -1, -1, -1,
                  IS_UNARY_OP | IS_BRANCH,
-                 "bl_2", "!0v"),
+                 "bl_2", "!0v", 1),
     ENCODING_MAP(ARMV5TE_BLX_R,         0x4780, 6, 3, -1, -1, -1, -1,
                  IS_UNARY_OP | IS_BRANCH,
-                 "blx", "r!0d"),
+                 "blx", "r!0d", 1),
     ENCODING_MAP(ARMV5TE_BX,            0x4700, 6, 3, -1, -1, -1, -1,
                  IS_UNARY_OP | IS_BRANCH,
-                 "bx", "r!0d"),
+                 "bx", "r!0d", 1),
     ENCODING_MAP(ARMV5TE_CMN,           0x42c0, 2, 0, 5, 3, -1, -1,
                  IS_BINARY_OP,
-                 "cmn", "r!0d, r!1d"),
+                 "cmn", "r!0d, r!1d", 1),
     ENCODING_MAP(ARMV5TE_CMP_RI8,       0x2800, 10, 8, 7, 0, -1, -1,
                  IS_BINARY_OP,
-                 "cmp", "r!0d, #!1d"),
+                 "cmp", "r!0d, #!1d", 1),
     ENCODING_MAP(ARMV5TE_CMP_RR,        0x4280, 2, 0, 5, 3, -1, -1,
                  IS_BINARY_OP,
-                 "cmp", "r!0d, r!1d"),
+                 "cmp", "r!0d, r!1d", 1),
     ENCODING_MAP(ARMV5TE_CMP_LH,        0x4540, 2, 0, 5, 3, -1, -1,
                  IS_BINARY_OP,
-                 "cmp", "r!0d, r!1D"),
+                 "cmp", "r!0d, r!1D", 1),
     ENCODING_MAP(ARMV5TE_CMP_HL,        0x4580, 2, 0, 5, 3, -1, -1,
                  IS_BINARY_OP,
-                 "cmp", "r!0D, r!1d"),
+                 "cmp", "r!0D, r!1d", 1),
     ENCODING_MAP(ARMV5TE_CMP_HH,        0x45c0, 2, 0, 5, 3, -1, -1,
                  IS_BINARY_OP,
-                 "cmp", "r!0D, r!1D"),
+                 "cmp", "r!0D, r!1D", 1),
     ENCODING_MAP(ARMV5TE_EOR,           0x4040, 2, 0, 5, 3, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
-                 "eor", "r!0d, r!1d"),
+                 "eor", "r!0d, r!1d", 1),
     ENCODING_MAP(ARMV5TE_LDMIA,         0xc800, 10, 8, 7, 0, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST | CLOBBER_SRC1,
-                 "ldmia", "r!0d!!, <!1R>"),
+                 "ldmia", "r!0d!!, <!1R>", 1),
     ENCODING_MAP(ARMV5TE_LDR_RRI5,      0x6800, 2, 0, 5, 3, 10, 6,
                  IS_TERTIARY_OP | CLOBBER_DEST,
-                 "ldr", "r!0d, [r!1d, #!2E]"),
+                 "ldr", "r!0d, [r!1d, #!2E]", 1),
     ENCODING_MAP(ARMV5TE_LDR_RRR,       0x5800, 2, 0, 5, 3, 8, 6,
                  IS_TERTIARY_OP | CLOBBER_DEST,
-                 "ldr", "r!0d, [r!1d, r!2d]"),
+                 "ldr", "r!0d, [r!1d, r!2d]", 1),
     ENCODING_MAP(ARMV5TE_LDR_PC_REL,    0x4800, 10, 8, 7, 0, -1, -1,
                  IS_TERTIARY_OP | CLOBBER_DEST,
-                 "ldr", "r!0d, [pc, #!1E]"),
+                 "ldr", "r!0d, [pc, #!1E]", 1),
     ENCODING_MAP(ARMV5TE_LDR_SP_REL,    0x9800, 10, 8, 7, 0, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
-                 "ldr", "r!0d, [sp, #!1E]"),
+                 "ldr", "r!0d, [sp, #!1E]", 1),
     ENCODING_MAP(ARMV5TE_LDRB_RRI5,     0x7800, 2, 0, 5, 3, 10, 6,
                  IS_TERTIARY_OP | CLOBBER_DEST,
-                 "ldrb", "r!0d, [r!1d, #2d]"),
+                 "ldrb", "r!0d, [r!1d, #2d]", 1),
     ENCODING_MAP(ARMV5TE_LDRB_RRR,      0x5c00, 2, 0, 5, 3, 8, 6,
                  IS_TERTIARY_OP | CLOBBER_DEST,
-                 "ldrb", "r!0d, [r!1d, r!2d]"),
+                 "ldrb", "r!0d, [r!1d, r!2d]", 1),
     ENCODING_MAP(ARMV5TE_LDRH_RRI5,     0x8800, 2, 0, 5, 3, 10, 6,
                  IS_TERTIARY_OP | CLOBBER_DEST,
-                 "ldrh", "r!0d, [r!1d, #!2F]"),
+                 "ldrh", "r!0d, [r!1d, #!2F]", 1),
     ENCODING_MAP(ARMV5TE_LDRH_RRR,      0x5a00, 2, 0, 5, 3, 8, 6,
                  IS_TERTIARY_OP | CLOBBER_DEST,
-                 "ldrh", "r!0d, [r!1d, r!2d]"),
+                 "ldrh", "r!0d, [r!1d, r!2d]", 1),
     ENCODING_MAP(ARMV5TE_LDRSB_RRR,     0x5600, 2, 0, 5, 3, 8, 6,
                  IS_TERTIARY_OP | CLOBBER_DEST,
-                 "ldrsb", "r!0d, [r!1d, r!2d]"),
+                 "ldrsb", "r!0d, [r!1d, r!2d]", 1),
     ENCODING_MAP(ARMV5TE_LDRSH_RRR,     0x5e00, 2, 0, 5, 3, 8, 6,
                  IS_TERTIARY_OP | CLOBBER_DEST,
-                 "ldrsh", "r!0d, [r!1d, r!2d]"),
+                 "ldrsh", "r!0d, [r!1d, r!2d]", 1),
     ENCODING_MAP(ARMV5TE_LSL,           0x0000, 2, 0, 5, 3, 10, 6,
                  IS_TERTIARY_OP | CLOBBER_DEST,
-                 "lsl", "r!0d, r!1d, #!2d"),
+                 "lsl", "r!0d, r!1d, #!2d", 1),
     ENCODING_MAP(ARMV5TE_LSLV,          0x4080, 2, 0, 5, 3, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
-                 "lsl", "r!0d, r!1d"),
+                 "lsl", "r!0d, r!1d", 1),
     ENCODING_MAP(ARMV5TE_LSR,           0x0800, 2, 0, 5, 3, 10, 6,
                  IS_TERTIARY_OP | CLOBBER_DEST,
-                 "lsr", "r!0d, r!1d, #!2d"),
+                 "lsr", "r!0d, r!1d, #!2d", 1),
     ENCODING_MAP(ARMV5TE_LSRV,          0x40c0, 2, 0, 5, 3, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
-                 "lsr", "r!0d, r!1d"),
+                 "lsr", "r!0d, r!1d", 1),
     ENCODING_MAP(ARMV5TE_MOV_IMM,       0x2000, 10, 8, 7, 0, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
-                 "mov", "r!0d, #!1d"),
+                 "mov", "r!0d, #!1d", 1),
     ENCODING_MAP(ARMV5TE_MOV_RR,        0x1c00, 2, 0, 5, 3, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
-                 "mov", "r!0d, r!1d"),
+                 "mov", "r!0d, r!1d", 1),
     ENCODING_MAP(ARMV5TE_MOV_RR_H2H,    0x46c0, 2, 0, 5, 3, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
-                 "mov", "r!0D, r!1D"),
+                 "mov", "r!0D, r!1D", 1),
     ENCODING_MAP(ARMV5TE_MOV_RR_H2L,    0x4640, 2, 0, 5, 3, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
-                 "mov", "r!0d, r!1D"),
+                 "mov", "r!0d, r!1D", 1),
     ENCODING_MAP(ARMV5TE_MOV_RR_L2H,    0x4680, 2, 0, 5, 3, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
-                 "mov", "r!0D, r!1d"),
+                 "mov", "r!0D, r!1d", 1),
     ENCODING_MAP(ARMV5TE_MUL,           0x4340, 2, 0, 5, 3, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
-                 "mul", "r!0d, r!1d"),
+                 "mul", "r!0d, r!1d", 1),
     ENCODING_MAP(ARMV5TE_MVN,           0x43c0, 2, 0, 5, 3, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
-                 "mvn", "r!0d, r!1d"),
+                 "mvn", "r!0d, r!1d", 1),
     ENCODING_MAP(ARMV5TE_NEG,           0x4240, 2, 0, 5, 3, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
-                 "neg", "r!0d, r!1d"),
+                 "neg", "r!0d, r!1d", 1),
     ENCODING_MAP(ARMV5TE_ORR,           0x4300, 2, 0, 5, 3, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
-                 "orr", "r!0d, r!1d"),
+                 "orr", "r!0d, r!1d", 1),
     ENCODING_MAP(ARMV5TE_POP,           0xbc00, 8, 0, -1, -1, -1, -1,
                  IS_UNARY_OP,
-                 "pop", "<!0R>"),
+                 "pop", "<!0R>", 1),
     ENCODING_MAP(ARMV5TE_PUSH,          0xb400, 8, 0, -1, -1, -1, -1,
                  IS_UNARY_OP,
-                 "push", "<!0R>"),
+                 "push", "<!0R>", 1),
     ENCODING_MAP(ARMV5TE_ROR,           0x41c0, 2, 0, 5, 3, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
-                 "ror", "r!0d, r!1d"),
+                 "ror", "r!0d, r!1d", 1),
     ENCODING_MAP(ARMV5TE_SBC,           0x4180, 2, 0, 5, 3, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
-                 "sbc", "r!0d, r!1d"),
+                 "sbc", "r!0d, r!1d", 1),
     ENCODING_MAP(ARMV5TE_STMIA,         0xc000, 10, 8, 7, 0, -1, -1,
                  IS_BINARY_OP | CLOBBER_SRC1,
-                 "stmia", "r!0d!!, <!1R>"),
+                 "stmia", "r!0d!!, <!1R>", 1),
     ENCODING_MAP(ARMV5TE_STR_RRI5,      0x6000, 2, 0, 5, 3, 10, 6,
                  IS_TERTIARY_OP,
-                 "str", "r!0d, [r!1d, #!2E]"),
+                 "str", "r!0d, [r!1d, #!2E]", 1),
     ENCODING_MAP(ARMV5TE_STR_RRR,       0x5000, 2, 0, 5, 3, 8, 6,
                  IS_TERTIARY_OP,
-                 "str", "r!0d, [r!1d, r!2d]"),
+                 "str", "r!0d, [r!1d, r!2d]", 1),
     ENCODING_MAP(ARMV5TE_STR_SP_REL,    0x9000, 10, 8, 7, 0, -1, -1,
                  IS_BINARY_OP,
-                 "str", "r!0d, [sp, #!1E]"),
+                 "str", "r!0d, [sp, #!1E]", 1),
     ENCODING_MAP(ARMV5TE_STRB_RRI5,     0x7000, 2, 0, 5, 3, 10, 6,
                  IS_TERTIARY_OP,
-                 "strb", "r!0d, [r!1d, #!2d]"),
+                 "strb", "r!0d, [r!1d, #!2d]", 1),
     ENCODING_MAP(ARMV5TE_STRB_RRR,      0x5400, 2, 0, 5, 3, 8, 6,
                  IS_TERTIARY_OP,
-                 "strb", "r!0d, [r!1d, r!2d]"),
+                 "strb", "r!0d, [r!1d, r!2d]", 1),
     ENCODING_MAP(ARMV5TE_STRH_RRI5,     0x8000, 2, 0, 5, 3, 10, 6,
                  IS_TERTIARY_OP,
-                 "strh", "r!0d, [r!1d, #!2F]"),
+                 "strh", "r!0d, [r!1d, #!2F]", 1),
     ENCODING_MAP(ARMV5TE_STRH_RRR,      0x5200, 2, 0, 5, 3, 8, 6,
                  IS_TERTIARY_OP,
-                 "strh", "r!0d, [r!1d, r!2d]"),
+                 "strh", "r!0d, [r!1d, r!2d]", 1),
     ENCODING_MAP(ARMV5TE_SUB_RRI3,      0x1e00, 2, 0, 5, 3, 8, 6,
                  IS_TERTIARY_OP | CLOBBER_DEST,
-                 "sub", "r!0d, r!1d, #!2d]"),
+                 "sub", "r!0d, r!1d, #!2d]", 1),
     ENCODING_MAP(ARMV5TE_SUB_RI8,       0x3800, 10, 8, 7, 0, -1, -1,
                  IS_BINARY_OP | CLOBBER_DEST,
-                 "sub", "r!0d, #!1d"),
+                 "sub", "r!0d, #!1d", 1),
     ENCODING_MAP(ARMV5TE_SUB_RRR,       0x1a00, 2, 0, 5, 3, 8, 6,
                  IS_TERTIARY_OP | CLOBBER_DEST,
-                 "sub", "r!0d, r!1d, r!2d"),
+                 "sub", "r!0d, r!1d, r!2d", 1),
     ENCODING_MAP(ARMV5TE_SUB_SPI7,      0xb080, 6, 0, -1, -1, -1, -1,
                  IS_UNARY_OP | CLOBBER_DEST,
-                 "sub", "sp, #!0d"),
+                 "sub", "sp, #!0d", 1),
     ENCODING_MAP(ARMV5TE_SWI,           0xdf00, 7, 0, -1, -1, -1, -1,
                  IS_UNARY_OP | IS_BRANCH,
-                 "swi", "!0d"),
+                 "swi", "!0d", 1),
     ENCODING_MAP(ARMV5TE_TST,           0x4200, 2, 0, 5, 3, -1, -1,
                  IS_UNARY_OP,
-                 "tst", "r!0d, r!1d"),
+                 "tst", "r!0d, r!1d", 1),
 };
 
 #define PADDING_MOV_R0_R0               0x1C00
@@ -441,7 +441,7 @@
  * before sending them off to the assembler. If out-of-range branch distance is
  * seen rearrange the instructions a bit to correct it.
  */
-void dvmCompilerAssembleLIR(CompilationUnit *cUnit)
+void dvmCompilerAssembleLIR(CompilationUnit *cUnit, JitTranslationInfo *info)
 {
     LIR *lir;
     Armv5teLIR *armLIR;
@@ -450,6 +450,9 @@
     ChainCellCounts chainCellCounts;
     int descSize = jitTraceDescriptionSize(cUnit->traceDesc);
 
+    info->codeAddress = NULL;
+    info->instructionSet = cUnit->instructionSet;
+
     /* Beginning offset needs to allow space for chain cell offset */
     for (armLIR = (Armv5teLIR *) cUnit->firstLIRInsn;
          armLIR;
@@ -553,6 +556,13 @@
     /* Flush dcache and invalidate the icache to maintain coherence */
     cacheflush((long)cUnit->baseAddr,
                (long)((char *) cUnit->baseAddr + offset), 0);
+
+    /* Record code entry point and instruction set */
+    info->codeAddress = (char*)cUnit->baseAddr + cUnit->headerSize;
+    info->instructionSet = cUnit->instructionSet;
+    /* If applicable, mark low bit to denote thumb */
+    if (info->instructionSet != DALVIK_JIT_ARM)
+        info->codeAddress = (char*)info->codeAddress + 1;
 }
 
 static u4 assembleBXPair(int branchOffset)
@@ -795,3 +805,137 @@
         dvmUnlockMutex(&gDvmJit.tableLock);
     }
 }
+
+typedef struct jitProfileAddrToLine {
+    u4 lineNum;
+    u4 bytecodeOffset;
+} jitProfileAddrToLine;
+
+
+/* Callback function to track the bytecode offset/line number relationiship */
+static int addrToLineCb (void *cnxt, u4 bytecodeOffset, u4 lineNum)
+{
+    jitProfileAddrToLine *addrToLine = (jitProfileAddrToLine *) cnxt;
+
+    /* Best match so far for this offset */
+    if (addrToLine->bytecodeOffset >= bytecodeOffset) {
+        addrToLine->lineNum = lineNum;
+    }
+    return 0;
+}
+
+char *getTraceBase(const JitEntry *p)
+{
+    return (char*)p->codeAddress -
+        (6 + (p->u.info.instructionSet == DALVIK_JIT_ARM ? 0 : 1));
+}
+
+/* Dumps profile info for a single trace */
+static int dumpTraceProfile(JitEntry *p)
+{
+    ChainCellCounts* pCellCounts;
+    char* traceBase;
+    u4* pExecutionCount;
+    u2* pCellOffset;
+    JitTraceDescription *desc;
+    const Method* method;
+
+    traceBase = getTraceBase(p);
+
+    if (p->codeAddress == NULL) {
+        LOGD("TRACEPROFILE 0x%08x 0 NULL 0 0", (int)traceBase);
+        return 0;
+    }
+
+    pExecutionCount = (u4*) (traceBase);
+    pCellOffset = (u2*) (traceBase + 4);
+    pCellCounts = (ChainCellCounts*) ((char *)pCellOffset + *pCellOffset);
+    desc = (JitTraceDescription*) ((char*)pCellCounts + sizeof(*pCellCounts));
+    method = desc->method;
+    char *methodDesc = dexProtoCopyMethodDescriptor(&method->prototype);
+    jitProfileAddrToLine addrToLine = {0, desc->trace[0].frag.startOffset};
+
+    /*
+     * We may end up decoding the debug information for the same method
+     * multiple times, but the tradeoff is we don't need to allocate extra
+     * space to store the addr/line mapping. Since this is a debugging feature
+     * and done infrequently so the slower but simpler mechanism should work
+     * just fine.
+     */
+    dexDecodeDebugInfo(method->clazz->pDvmDex->pDexFile,
+                       dvmGetMethodCode(method),
+                       method->clazz->descriptor,
+                       method->prototype.protoIdx,
+                       method->accessFlags,
+                       addrToLineCb, NULL, &addrToLine);
+
+    LOGD("TRACEPROFILE 0x%08x % 10d [%#x(+%d), %d] %s%s;%s",
+         (int)traceBase,
+         *pExecutionCount,
+         desc->trace[0].frag.startOffset,
+         desc->trace[0].frag.numInsts,
+         addrToLine.lineNum,
+         method->clazz->descriptor, method->name, methodDesc);
+    free(methodDesc);
+
+    return *pExecutionCount;
+}
+
+/* Handy function to retrieve the profile count */
+static inline int getProfileCount(const JitEntry *entry)
+{
+    if (entry->dPC == 0 || entry->codeAddress == 0)
+        return 0;
+    u4 *pExecutionCount = (u4 *) getTraceBase(entry);
+
+    return *pExecutionCount;
+}
+
+
+/* qsort callback function */
+static int sortTraceProfileCount(const void *entry1, const void *entry2)
+{
+    const JitEntry *jitEntry1 = entry1;
+    const JitEntry *jitEntry2 = entry2;
+
+    int count1 = getProfileCount(jitEntry1);
+    int count2 = getProfileCount(jitEntry2);
+    return (count1 == count2) ? 0 : ((count1 > count2) ? -1 : 1);
+}
+
+/* Sort the trace profile counts and dump them */
+void dvmCompilerSortAndPrintTraceProfiles()
+{
+    JitEntry *sortedEntries;
+    int numTraces = 0;
+    unsigned long counts = 0;
+    unsigned int i;
+
+    /* Make sure that the table is not changing */
+    dvmLockMutex(&gDvmJit.tableLock);
+
+    /* Sort the entries by descending order */
+    sortedEntries = malloc(sizeof(JitEntry) * gDvmJit.jitTableSize);
+    if (sortedEntries == NULL)
+        goto done;
+    memcpy(sortedEntries, gDvmJit.pJitEntryTable,
+           sizeof(JitEntry) * gDvmJit.jitTableSize);
+    qsort(sortedEntries, gDvmJit.jitTableSize, sizeof(JitEntry),
+          sortTraceProfileCount);
+
+    /* Dump the sorted entries */
+    for (i=0; i < gDvmJit.jitTableSize; i++) {
+        if (sortedEntries[i].dPC != 0) {
+            counts += dumpTraceProfile(&sortedEntries[i]);
+            numTraces++;
+        }
+    }
+    if (numTraces == 0)
+        numTraces = 1;
+    LOGD("JIT: Average execution count -> %d",(int)(counts / numTraces));
+
+    free(sortedEntries);
+done:
+    dvmUnlockMutex(&gDvmJit.tableLock);
+    return;
+}
diff --git a/vm/compiler/codegen/armv5te/Codegen.c b/vm/compiler/codegen/armv5te/Codegen.c
index 6d19472..b8f4da4 100644
--- a/vm/compiler/codegen/armv5te/Codegen.c
+++ b/vm/compiler/codegen/armv5te/Codegen.c
@@ -3544,24 +3544,24 @@
 }
 
 /* Accept the work and start compiling */
-void *dvmCompilerDoWork(CompilerWorkOrder *work)
+bool dvmCompilerDoWork(CompilerWorkOrder *work)
 {
-   void *res;
+   bool res;
 
    if (gDvmJit.codeCacheFull) {
-       return NULL;
+       return false;
    }
 
    switch (work->kind) {
        case kWorkOrderMethod:
-           res = dvmCompileMethod(work->info);
+           res = dvmCompileMethod(work->info, &work->result);
            break;
        case kWorkOrderTrace:
            /* Start compilation with maximally allowed trace length */
-           res = dvmCompileTrace(work->info, JIT_MAX_TRACE_LEN);
+           res = dvmCompileTrace(work->info, JIT_MAX_TRACE_LEN, &work->result);
            break;
        default:
-           res = NULL;
+           res = false;
            dvmAbort();
    }
    return res;
diff --git a/vm/compiler/codegen/armv5te/armv5te-vfp/ArchVariant.c b/vm/compiler/codegen/armv5te/armv5te-vfp/ArchVariant.c
index 4c97897..583cf00 100644
--- a/vm/compiler/codegen/armv5te/armv5te-vfp/ArchVariant.c
+++ b/vm/compiler/codegen/armv5te/armv5te-vfp/ArchVariant.c
@@ -22,6 +22,15 @@
 #define USE_IN_CACHE_HANDLER 1
 
 /*
+ * Determine the initial instruction set to be used for this trace.
+ * Later components may decide to change this.
+ */
+JitInstructionSetType dvmCompilerInstructionSet(CompilationUnit *cUnit)
+{
+    return DALVIK_JIT_THUMB;
+}
+
+/*
  * Jump to the out-of-line handler in ARM mode to finish executing the
  * remaining of more complex instructions.
  */
diff --git a/vm/compiler/codegen/armv5te/armv5te/ArchVariant.c b/vm/compiler/codegen/armv5te/armv5te/ArchVariant.c
index 3d9d014..d0122c8 100644
--- a/vm/compiler/codegen/armv5te/armv5te/ArchVariant.c
+++ b/vm/compiler/codegen/armv5te/armv5te/ArchVariant.c
@@ -22,6 +22,15 @@
 #define USE_IN_CACHE_HANDLER 1
 
 /*
+ * Determine the initial instruction set to be used for this trace.
+ * Later components may decide to change this.
+ */
+JitInstructionSetType dvmCompilerInstructionSet(CompilationUnit *cUnit)
+{
+    return DALVIK_JIT_THUMB;
+}
+
+/*
  * Jump to the out-of-line handler in ARM mode to finish executing the
  * remaining of more complex instructions.
  */