OSDN Git Service

Implement method parser and SSA transformation.
authorBen Cheng <bccheng@android.com>
Thu, 28 Oct 2010 18:13:58 +0000 (11:13 -0700)
committerBen Cheng <bccheng@android.com>
Tue, 14 Dec 2010 00:49:33 +0000 (16:49 -0800)
Change-Id: If3fb3a36f33aaee8e5fdded4e9fa607be54f0bfb

20 files changed:
vm/BitVector.c
vm/BitVector.h
vm/Dvm.mk
vm/Misc.h
vm/compiler/Compiler.h
vm/compiler/CompilerIR.h
vm/compiler/CompilerUtility.h
vm/compiler/Dataflow.c
vm/compiler/Frontend.c
vm/compiler/InlineTransformation.c
vm/compiler/IntermediateRep.c
vm/compiler/Loop.c
vm/compiler/MethodSSATransformation.c [new file with mode: 0644]
vm/compiler/Ralloc.c
vm/compiler/Utility.c
vm/compiler/codegen/arm/CodegenCommon.c
vm/compiler/codegen/arm/CodegenDriver.c
vm/mterp/out/InterpC-allstubs.c
vm/mterp/out/InterpC-x86-atom.c
vm/mterp/out/InterpC-x86.c

index 68f19b0..04c3d3f 100644 (file)
@@ -143,6 +143,24 @@ void dvmClearAllBits(BitVector* pBits)
 }
 
 /*
+ * Mark specified number of bits as "set". Cannot set all bits like ClearAll
+ * since there might be unused bits - setting those to one will confuse the
+ * iterator.
+ */
+void dvmSetInitialBits(BitVector* pBits, int numBits)
+{
+    int i;
+    assert(((numBits + 31) >> 5) <= pBits->storageSize);
+    for (i = 0; i < (numBits >> 5); i++) {
+        pBits->storage[i] = -1;
+    }
+    int remNumBits = numBits & 0x1f;
+    if (remNumBits) {
+        pBits->storage[i] = (1 << remNumBits) - 1;
+    }
+}
+
+/*
  * Determine whether or not the specified bit is set.
  */
 bool dvmIsBitSet(const BitVector* pBits, int num)
@@ -194,8 +212,7 @@ bool dvmCopyBitVector(BitVector *dest, const BitVector *src)
 }
 
 /*
- * Intersect two bit vectores and merge the result on top of the pre-existing
- * value in the dest vector.
+ * Intersect two bit vectors and store the result to the dest vector.
  */
 bool dvmIntersectBitVectors(BitVector *dest, const BitVector *src1,
                             const BitVector *src2)
@@ -208,7 +225,71 @@ bool dvmIntersectBitVectors(BitVector *dest, const BitVector *src1,
 
     int i;
     for (i = 0; i < dest->storageSize; i++) {
-        dest->storage[i] |= src1->storage[i] & src2->storage[i];
+        dest->storage[i] = src1->storage[i] & src2->storage[i];
     }
     return true;
 }
+
+/*
+ * Unify two bit vectors and store the result to the dest vector.
+ */
+bool dvmUnifyBitVectors(BitVector *dest, const BitVector *src1,
+                        const BitVector *src2)
+{
+    if (dest->storageSize != src1->storageSize ||
+        dest->storageSize != src2->storageSize ||
+        dest->expandable != src1->expandable ||
+        dest->expandable != src2->expandable)
+        return false;
+
+    int i;
+    for (i = 0; i < dest->storageSize; i++) {
+        dest->storage[i] = src1->storage[i] | src2->storage[i];
+    }
+    return true;
+}
+
+/*
+ * Compare two bit vectors and return true if difference is seen.
+ */
+bool dvmCompareBitVectors(const BitVector *src1, const BitVector *src2)
+{
+    if (src1->storageSize != src2->storageSize ||
+        src1->expandable != src2->expandable)
+        return true;
+
+    int i;
+    for (i = 0; i < src1->storageSize; i++) {
+        if (src1->storage[i] != src2->storage[i]) return true;
+    }
+    return false;
+}
+
+/* Initialize the iterator structure */
+void dvmBitVectorIteratorInit(BitVector* pBits, BitVectorIterator* iterator)
+{
+    iterator->pBits = pBits;
+    iterator->bitSize = pBits->storageSize * sizeof(u4) * 8;
+    iterator->idx = 0;
+}
+
+/* Return the next position set to 1. -1 means end-of-element reached */
+int dvmBitVectorIteratorNext(BitVectorIterator* iterator)
+{
+    const BitVector* pBits = iterator->pBits;
+    u4 bitIndex = iterator->idx;
+
+    assert(iterator->bitSize == pBits->storageSize * sizeof(u4) * 8);
+    if (bitIndex >= iterator->bitSize) return -1;
+
+    for (; bitIndex < iterator->bitSize; bitIndex++) {
+        int wordIndex = bitIndex >> 5;
+        int mask = 1 << (bitIndex & 0x1f);
+        if (pBits->storage[wordIndex] & mask) {
+            iterator->idx = bitIndex+1;
+            return bitIndex;
+        }
+    }
+    /* No more set bits */
+    return -1;
+}
index 94abe7b..3c926b1 100644 (file)
@@ -32,6 +32,13 @@ typedef struct BitVector {
     u4*     storage;
 } BitVector;
 
+/* Handy iterator to walk through the bit positions set to 1 */
+typedef struct BitVectorIterator {
+    BitVector *pBits;
+    u4 idx;
+    u4 bitSize;
+} BitVectorIterator;
+
 /* allocate a bit vector with enough space to hold "startBits" bits */
 BitVector* dvmAllocBitVector(int startBits, bool expandable);
 void dvmFreeBitVector(BitVector* pBits);
@@ -44,12 +51,15 @@ void dvmFreeBitVector(BitVector* pBits);
  * dvmSetBit sets the specified bit, expanding the vector if necessary
  * (and possible).
  *
+ * dvmSetInitialBits sets all bits in [0..numBits-1]. Won't expand the vector.
+ *
  * dvmIsBitSet returns "true" if the bit is set.
  */
 int dvmAllocBit(BitVector* pBits);
 bool dvmSetBit(BitVector* pBits, int num);
 void dvmClearBit(BitVector* pBits, int num);
 void dvmClearAllBits(BitVector* pBits);
+void dvmSetInitialBits(BitVector* pBits, int numBits);
 bool dvmIsBitSet(const BitVector* pBits, int num);
 
 /* count the number of bits that have been set */
@@ -59,11 +69,26 @@ int dvmCountSetBits(const BitVector* pBits);
 bool dvmCopyBitVector(BitVector *dest, const BitVector *src);
 
 /*
- * Intersect two bit vectores and merge the result on top of the pre-existing
- * value in the dest vector.
+ * Intersect two bit vectors and store the result to the dest vector.
  */
 bool dvmIntersectBitVectors(BitVector *dest, const BitVector *src1,
                             const BitVector *src2);
 
+/*
+ * Unify two bit vectors and store the result to the dest vector.
+ */
+bool dvmUnifyBitVectors(BitVector *dest, const BitVector *src1,
+                        const BitVector *src2);
+
+/*
+ * Compare two bit vectors and return true if difference is seen.
+ */
+bool dvmCompareBitVectors(const BitVector *src1, const BitVector *src2);
+
+/* Initialize the iterator structure */
+void dvmBitVectorIteratorInit(BitVector* pBits, BitVectorIterator* iterator);
+
+/* Return the next position set to 1. -1 means end-of-vector reached */
+int dvmBitVectorIteratorNext(BitVectorIterator* iterator);
 
 #endif /*_DALVIK_BITVECTOR*/
index 18165d2..4711ffd 100644 (file)
--- a/vm/Dvm.mk
+++ b/vm/Dvm.mk
@@ -224,6 +224,7 @@ ifeq ($(WITH_JIT),true)
        compiler/InlineTransformation.c \
        compiler/IntermediateRep.c \
        compiler/Dataflow.c \
+       compiler/MethodSSATransformation.c \
        compiler/Loop.c \
        compiler/Ralloc.c \
        interp/Jit.c
index ee0a4eb..4dc983e 100644 (file)
--- a/vm/Misc.h
+++ b/vm/Misc.h
@@ -128,7 +128,6 @@ void dvmPrintDebugMessage(const DebugOutputTarget* target, const char* format,
 #endif
     ;
 
-
 /*
  * Return a newly-allocated string in which all occurrences of '.' have
  * been changed to '/'.  If we find a '/' in the original string, NULL
index 6dd9cbd..0a43df3 100644 (file)
@@ -236,6 +236,15 @@ typedef enum JitOptimizationHints {
 
 #define JIT_OPT_NO_LOOP         (1 << kJitOptNoLoop)
 
+/* Customized node traversal orders for different needs */
+typedef enum DataFlowAnalysisMode {
+    kAllNodes = 0,              // All nodes
+    kReachableNodes,            // All reachable nodes
+    kPreOrderDFSTraversal,      // Depth-First-Search / Pre-Order
+    kPostOrderDFSTraversal,     // Depth-First-Search / Post-Order
+    kPostOrderDOMTraversal,     // Dominator tree / Post-Order
+} DataFlowAnalysisMode;
+
 typedef struct CompilerMethodStats {
     const Method *method;       // Used as hash entry signature
     int dalvikSize;             // # of bytes for dalvik bytecodes
@@ -262,8 +271,7 @@ CompilerMethodStats *dvmCompilerAnalyzeMethodBody(const Method *method,
                                                   bool isCallee);
 bool dvmCompilerCanIncludeThisInstruction(const Method *method,
                                           const DecodedInstruction *insn);
-bool dvmCompileMethod(struct CompilationUnit *cUnit, const Method *method,
-                      JitTranslationInfo *info);
+bool dvmCompileMethod(const Method *method);
 bool dvmCompileTrace(JitTraceDescription *trace, int numMaxInsts,
                      JitTranslationInfo *info, jmp_buf *bailPtr, int optHints);
 void dvmCompilerDumpStats(void);
@@ -273,22 +281,31 @@ void dvmCompilerSortAndPrintTraceProfiles(void);
 void dvmCompilerPerformSafePointChecks(void);
 void dvmCompilerInlineMIR(struct CompilationUnit *cUnit);
 void dvmInitializeSSAConversion(struct CompilationUnit *cUnit);
-int dvmConvertSSARegToDalvik(struct CompilationUnit *cUnit, int ssaReg);
+int dvmConvertSSARegToDalvik(const struct CompilationUnit *cUnit, int ssaReg);
 bool dvmCompilerLoopOpt(struct CompilationUnit *cUnit);
 void dvmCompilerNonLoopAnalysis(struct CompilationUnit *cUnit);
-void dvmCompilerFindLiveIn(struct CompilationUnit *cUnit,
-                           struct BasicBlock *bb);
-void dvmCompilerDoSSAConversion(struct CompilationUnit *cUnit,
+bool dvmCompilerFindLocalLiveIn(struct CompilationUnit *cUnit,
+                                struct BasicBlock *bb);
+bool dvmCompilerDoSSAConversion(struct CompilationUnit *cUnit,
                                 struct BasicBlock *bb);
-void dvmCompilerDoConstantPropagation(struct CompilationUnit *cUnit,
+bool dvmCompilerDoConstantPropagation(struct CompilationUnit *cUnit,
                                       struct BasicBlock *bb);
-void dvmCompilerFindInductionVariables(struct CompilationUnit *cUnit,
+bool dvmCompilerFindInductionVariables(struct CompilationUnit *cUnit,
                                        struct BasicBlock *bb);
-char *dvmCompilerGetDalvikDisassembly(DecodedInstruction *insn, char *note);
+/* Clear the visited flag for each BB */
+bool dvmCompilerClearVisitedFlag(struct CompilationUnit *cUnit,
+                                 struct BasicBlock *bb);
+char *dvmCompilerGetDalvikDisassembly(const DecodedInstruction *insn,
+                                      char *note);
+char *dvmCompilerFullDisassembler(const struct CompilationUnit *cUnit,
+                                  const struct MIR *mir);
 char *dvmCompilerGetSSAString(struct CompilationUnit *cUnit,
                               struct SSARepresentation *ssaRep);
 void dvmCompilerDataFlowAnalysisDispatcher(struct CompilationUnit *cUnit,
-                void (*func)(struct CompilationUnit *, struct BasicBlock *));
+                bool (*func)(struct CompilationUnit *, struct BasicBlock *),
+                DataFlowAnalysisMode dfaMode,
+                bool isIterative);
+void dvmCompilerMethodSSATransformation(struct CompilationUnit *cUnit);
 void dvmCompilerStateRefresh(void);
 JitTraceDescription *dvmCopyTraceDescriptor(const u2 *pc,
                                             const struct JitEntry *desc);
index 712ca4c..95a75b8 100644 (file)
@@ -61,6 +61,7 @@ typedef enum BBType {
     kMethodExitBlock,
     kPCReconstruction,
     kExceptionHandling,
+    kCatchEntry,
 } BBType;
 
 typedef struct ChainCellCounts {
@@ -133,20 +134,47 @@ typedef struct MIR {
 
 struct BasicBlockDataFlow;
 
+/* FIXME - debugging prupose only */
+typedef enum BlockAttributes {
+    kEndsWithThrow = 0,
+    kCatchBlock,
+} BlockAttributes;
+
+/* For successorBlockList */
+typedef enum BlockListType {
+    kNotUsed = 0,
+    kCatch,
+    kPackedSwitch,
+    kSparseSwitch,
+} BlockListType;
+
+#define BA_ENDS_WITH_THROW              (1 << kEndsWithThrow)
+#define BA_CATCH_BLOCK                  (1 << kCatchBlock)
+
 typedef struct BasicBlock {
     int id;
-    int visited;
+    bool visited;
     unsigned int startOffset;
     const Method *containingMethod;     // For blocks from the callee
     BBType blockType;
     bool needFallThroughBranch;         // For blocks ended due to length limit
     bool isFallThroughFromInvoke;       // True means the block needs alignment
+    u4 blockAttributes;                 // FIXME - debugging purpose only
+    u4 exceptionTypeIdx;                // FIXME - will be put elsewhere
     MIR *firstMIRInsn;
     MIR *lastMIRInsn;
     struct BasicBlock *fallThrough;
     struct BasicBlock *taken;
-    struct BasicBlock *next;            // Serial link for book keeping purposes
+    struct BasicBlock *iDom;            // Immediate dominator
     struct BasicBlockDataFlow *dataFlowInfo;
+    BitVector *predecessors;
+    BitVector *dominators;
+    BitVector *iDominated;              // Set nodes being immediately dominated
+    BitVector *domFrontier;             // Dominance frontier
+    struct {                            // For one-to-many successors like
+        BlockListType blockListType;    // switch and exception handling
+        GrowableList blocks;
+    } successorBlockList;
 } BasicBlock;
 
 struct LoopAnalysis;
@@ -161,7 +189,7 @@ typedef enum AssemblerStatus {
 typedef struct CompilationUnit {
     int numInsts;
     int numBlocks;
-    BasicBlock **blockList;
+    GrowableList blockList;
     const Method *method;
     const JitTraceDescription *traceDesc;
     LIR *firstLIRInsn;
@@ -213,6 +241,20 @@ typedef struct CompilationUnit {
      * MAX_CHAINED_SWITCH_CASES cases.
      */
     const u2 *switchOverflowPad;
+
+    /* New fields only for method-based compilation */
+    int numReachableBlocks;
+    int numDalvikRegisters;             // method->registersSize + inlined
+    BasicBlock *entryBlock;
+    BasicBlock *exitBlock;
+    GrowableList dfsOrder;
+    GrowableList domPostOrderTraversal;
+    BitVector *tryBlockAddr;
+    BitVector **defBlockMatrix;         // numDalvikRegister x numBlocks
+    BitVector *tempBlockV;
+    BitVector *tempDalvikRegisterV;
+    BitVector *tempSSARegisterV;        // numSSARegs
+    bool printSSANames;
 } CompilationUnit;
 
 #if defined(WITH_SELF_VERIFICATION)
@@ -221,7 +263,7 @@ typedef struct CompilationUnit {
 #define HEAP_ACCESS_SHADOW(_state)
 #endif
 
-BasicBlock *dvmCompilerNewBB(BBType blockType);
+BasicBlock *dvmCompilerNewBB(BBType blockType, int blockId);
 
 void dvmCompilerAppendMIR(BasicBlock *bb, MIR *mir);
 
index 551edb8..d3f2d6a 100644 (file)
@@ -39,19 +39,39 @@ void dvmCompilerArenaReset(void);
 typedef struct GrowableList {
     size_t numAllocated;
     size_t numUsed;
-    void **elemList;
+    intptr_t *elemList;
 } GrowableList;
 
+typedef struct GrowableListIterator {
+    GrowableList *list;
+    size_t idx;
+    size_t size;
+} GrowableListIterator;
+
 #define GET_ELEM_N(LIST, TYPE, N) (((TYPE*) LIST->elemList)[N])
 
+#define BLOCK_NAME_LEN 80
+
+/* Forward declarations */
 struct LIR;
+struct BasicBlock;
 
 void dvmInitGrowableList(GrowableList *gList, size_t initLength);
-void dvmInsertGrowableList(GrowableList *gList, void *elem);
+void dvmInsertGrowableList(GrowableList *gList, intptr_t elem);
+void dvmGrowableListIteratorInit(GrowableList *gList,
+                                 GrowableListIterator *iterator);
+intptr_t dvmGrowableListIteratorNext(GrowableListIterator *iterator);
+intptr_t dvmGrowableListGetElement(const GrowableList *gList, size_t idx);
+
 BitVector* dvmCompilerAllocBitVector(int startBits, bool expandable);
 bool dvmCompilerSetBit(BitVector* pBits, int num);
+bool dvmCompilerClearBit(BitVector* pBits, int num);
+void dvmCompilerMarkAllBits(BitVector *pBits, bool set);
 void dvmDebugBitVector(char *msg, const BitVector *bv, int length);
 void dvmDumpLIRInsn(struct LIR *lir, unsigned char *baseAddr);
 void dvmDumpResourceMask(struct LIR *lir, u8 mask, const char *prefix);
+void dvmDumpBlockBitVector(const GrowableList *blocks, char *msg,
+                           const BitVector *bv, int length);
+void dvmGetBlockName(struct BasicBlock *bb, char *name);
 
 #endif /* _DALVIK_COMPILER_UTILITY */
index da1bf24..411f456 100644 (file)
@@ -809,7 +809,7 @@ int dvmCompilerDataFlowAttributes[kMirOpLast] = {
 };
 
 /* Return the Dalvik register/subscript pair of a given SSA register */
-int dvmConvertSSARegToDalvik(CompilationUnit *cUnit, int ssaReg)
+int dvmConvertSSARegToDalvik(const CompilationUnit *cUnit, int ssaReg)
 {
       return GET_ELEM_N(cUnit->ssaToDalvikMap, int, ssaReg);
 }
@@ -819,21 +819,58 @@ int dvmConvertSSARegToDalvik(CompilationUnit *cUnit, int ssaReg)
  * and subscript pair. Each SSA register can be used to index the
  * ssaToDalvikMap list to get the subscript[31..16]/dalvik_reg[15..0] mapping.
  */
-char *dvmCompilerGetDalvikDisassembly(DecodedInstruction *insn,
+char *dvmCompilerGetDalvikDisassembly(const DecodedInstruction *insn,
                                       char *note)
 {
     char buffer[256];
     int opcode = insn->opcode;
     int dfAttributes = dvmCompilerDataFlowAttributes[opcode];
+    int flags = dexGetFlagsFromOpcode(insn->opcode);
     char *ret;
 
     buffer[0] = 0;
-    strcpy(buffer, dexGetOpcodeName(opcode));
+    if (opcode >= kMirOpFirst) {
+        if (opcode == kMirOpPhi) {
+            strcpy(buffer, "PHI");
+        }
+        else {
+            sprintf(buffer, "Opcode 0x%x", opcode);
+        }
+    } else {
+        strcpy(buffer, dexGetOpcodeName(opcode));
+    }
 
     if (note)
         strcat(buffer, note);
 
-    if (dfAttributes & DF_FORMAT_35C) {
+    /* For branches, decode the instructions to print out the branch targets */
+    if (flags & kInstrCanBranch) {
+        InstructionFormat dalvikFormat = dexGetFormatFromOpcode(insn->opcode);
+        int offset = 0;
+        switch (dalvikFormat) {
+            case kFmt21t:
+                snprintf(buffer + strlen(buffer), 256, " v%d,", insn->vA);
+                offset = (int) insn->vB;
+                break;
+            case kFmt22t:
+                snprintf(buffer + strlen(buffer), 256, " v%d, v%d,",
+                         insn->vA, insn->vB);
+                offset = (int) insn->vC;
+                break;
+            case kFmt10t:
+            case kFmt20t:
+            case kFmt30t:
+                offset = (int) insn->vA;
+                break;
+            default:
+                LOGE("Unexpected branch format: %d", dalvikFormat);
+                dvmAbort();
+                break;
+        }
+        snprintf(buffer + strlen(buffer), 256, " (%c%x)",
+                 offset > 0 ? '+' : '-',
+                 offset > 0 ? offset : -offset);
+    } else if (dfAttributes & DF_FORMAT_35C) {
         unsigned int i;
         for (i = 0; i < insn->vA; i++) {
             if (i != 0) strcat(buffer, ",");
@@ -851,13 +888,13 @@ char *dvmCompilerGetDalvikDisassembly(DecodedInstruction *insn,
         if (dfAttributes & DF_B_IS_REG) {
             snprintf(buffer + strlen(buffer), 256, ", v%d", insn->vB);
         }
-        else {
+        else if (opcode < kMirOpFirst) {
             snprintf(buffer + strlen(buffer), 256, ", (#%d)", insn->vB);
         }
         if (dfAttributes & DF_C_IS_REG) {
             snprintf(buffer + strlen(buffer), 256, ", v%d", insn->vC);
         }
-        else {
+        else if (opcode < kMirOpFirst) {
             snprintf(buffer + strlen(buffer), 256, ", (#%d)", insn->vC);
         }
     }
@@ -867,6 +904,141 @@ char *dvmCompilerGetDalvikDisassembly(DecodedInstruction *insn,
     return ret;
 }
 
+char *getSSAName(const CompilationUnit *cUnit, int ssaReg, char *name)
+{
+    int ssa2DalvikValue = dvmConvertSSARegToDalvik(cUnit, ssaReg);
+
+    sprintf(name, "v%d_%d",
+            DECODE_REG(ssa2DalvikValue), DECODE_SUB(ssa2DalvikValue));
+    return name;
+}
+
+/*
+ * Dalvik instruction disassembler with optional SSA printing.
+ */
+char *dvmCompilerFullDisassembler(const CompilationUnit *cUnit,
+                                  const MIR *mir)
+{
+    char buffer[256];
+    char operand0[256], operand1[256];
+    const DecodedInstruction *insn = &mir->dalvikInsn;
+    int opcode = insn->opcode;
+    int dfAttributes = dvmCompilerDataFlowAttributes[opcode];
+    int flags = dexGetFlagsFromOpcode(insn->opcode);
+    char *ret;
+    int length;
+
+    buffer[0] = 0;
+    if (opcode >= kMirOpFirst) {
+        if (opcode == kMirOpPhi) {
+            snprintf(buffer, 256, "PHI %s = (%s",
+                     getSSAName(cUnit, mir->ssaRep->defs[0], operand0),
+                     getSSAName(cUnit, mir->ssaRep->uses[0], operand1));
+            int i;
+            for (i = 1; i < mir->ssaRep->numUses; i++) {
+                snprintf(buffer + strlen(buffer), 256, ", %s",
+                         getSSAName(cUnit, mir->ssaRep->uses[i], operand0));
+            }
+            snprintf(buffer + strlen(buffer), 256, ")");
+        }
+        else {
+            sprintf(buffer, "Opcode 0x%x", opcode);
+        }
+        goto done;
+    } else {
+        strcpy(buffer, dexGetOpcodeName(opcode));
+    }
+
+    /* For branches, decode the instructions to print out the branch targets */
+    if (flags & kInstrCanBranch) {
+        InstructionFormat dalvikFormat = dexGetFormatFromOpcode(insn->opcode);
+        int delta = 0;
+        switch (dalvikFormat) {
+            case kFmt21t:
+                snprintf(buffer + strlen(buffer), 256, " %s, ",
+                         getSSAName(cUnit, mir->ssaRep->uses[0], operand0));
+                delta = (int) insn->vB;
+                break;
+            case kFmt22t:
+                snprintf(buffer + strlen(buffer), 256, " %s, %s, ",
+                         getSSAName(cUnit, mir->ssaRep->uses[0], operand0),
+                         getSSAName(cUnit, mir->ssaRep->uses[1], operand1));
+                delta = (int) insn->vC;
+                break;
+            case kFmt10t:
+            case kFmt20t:
+            case kFmt30t:
+                delta = (int) insn->vA;
+                break;
+            default:
+                LOGE("Unexpected branch format: %d", dalvikFormat);
+                dvmAbort();
+                break;
+        }
+        snprintf(buffer + strlen(buffer), 256, " %04x",
+                 mir->offset + delta);
+    } else if (dfAttributes & (DF_FORMAT_35C | DF_FORMAT_3RC)) {
+        unsigned int i;
+        for (i = 0; i < insn->vA; i++) {
+            if (i != 0) strcat(buffer, ",");
+            snprintf(buffer + strlen(buffer), 256, " %s",
+                     getSSAName(cUnit, mir->ssaRep->uses[i], operand0));
+        }
+    } else {
+        int udIdx;
+        if (mir->ssaRep->numDefs) {
+
+            for (udIdx = 0; udIdx < mir->ssaRep->numDefs; udIdx++) {
+                snprintf(buffer + strlen(buffer), 256, " %s",
+                         getSSAName(cUnit, mir->ssaRep->defs[udIdx], operand0));
+            }
+            strcat(buffer, ",");
+        }
+        if (mir->ssaRep->numUses) {
+            /* No leading ',' for the first use */
+            snprintf(buffer + strlen(buffer), 256, " %s",
+                     getSSAName(cUnit, mir->ssaRep->uses[0], operand0));
+            for (udIdx = 1; udIdx < mir->ssaRep->numUses; udIdx++) {
+                snprintf(buffer + strlen(buffer), 256, ", %s",
+                         getSSAName(cUnit, mir->ssaRep->uses[udIdx], operand0));
+            }
+        }
+        if (opcode < kMirOpFirst) {
+            InstructionFormat dalvikFormat = dexGetFormatFromOpcode(opcode);
+            switch (dalvikFormat) {
+                case kFmt11n:        // op vA, #+B
+                case kFmt21s:        // op vAA, #+BBBB
+                case kFmt21h:        // op vAA, #+BBBB00000[00000000]
+                case kFmt31i:        // op vAA, #+BBBBBBBB
+                case kFmt51l:        // op vAA, #+BBBBBBBBBBBBBBBB
+                    snprintf(buffer + strlen(buffer), 256, " #%#x", insn->vB);
+                    break;
+                case kFmt21c:        // op vAA, thing@BBBB
+                case kFmt31c:        // op vAA, thing@BBBBBBBB
+                    snprintf(buffer + strlen(buffer), 256, " @%#x", insn->vB);
+                    break;
+                case kFmt22b:        // op vAA, vBB, #+CC
+                case kFmt22s:        // op vA, vB, #+CCCC
+                    snprintf(buffer + strlen(buffer), 256, " #%#x", insn->vC);
+                    break;
+                case kFmt22c:        // op vA, vB, thing@CCCC
+                case kFmt22cs:       // [opt] op vA, vB, field offset CCCC
+                    snprintf(buffer + strlen(buffer), 256, " @%#x", insn->vC);
+                    break;
+                    /* No need for special printing */
+                default:
+                    break;
+            }
+        }
+    }
+
+done:
+    length = strlen(buffer) + 1;
+    ret = (char *) dvmCompilerNew(length, false);
+    memcpy(ret, buffer, length);
+    return ret;
+}
+
 /*
  * Utility function to convert encoded SSA register value into Dalvik register
  * and subscript pair. Each SSA register can be used to index the
@@ -920,7 +1092,7 @@ static inline void handleLiveInUse(BitVector *useV, BitVector *defV,
 }
 
 /* Mark a reg as being defined */
-static inline void handleLiveInDef(BitVector *defV, int dalvikRegId)
+static inline void handleDef(BitVector *defV, int dalvikRegId)
 {
     dvmCompilerSetBit(defV, dalvikRegId);
 }
@@ -929,22 +1101,19 @@ static inline void handleLiveInDef(BitVector *defV, int dalvikRegId)
  * Find out live-in variables for natural loops. Variables that are live-in in
  * the main loop body are considered to be defined in the entry block.
  */
-void dvmCompilerFindLiveIn(CompilationUnit *cUnit, BasicBlock *bb)
+bool dvmCompilerFindLocalLiveIn(CompilationUnit *cUnit, BasicBlock *bb)
 {
     MIR *mir;
     BitVector *useV, *defV, *liveInV;
 
-    if (bb->blockType != kDalvikByteCode &&
-        bb->blockType != kTraceEntryBlock) {
-        return;
-    }
+    if (bb->dataFlowInfo == NULL) return false;
 
     useV = bb->dataFlowInfo->useV =
-        dvmCompilerAllocBitVector(cUnit->method->registersSize, false);
+        dvmCompilerAllocBitVector(cUnit->numDalvikRegisters, false);
     defV = bb->dataFlowInfo->defV =
-        dvmCompilerAllocBitVector(cUnit->method->registersSize, false);
+        dvmCompilerAllocBitVector(cUnit->numDalvikRegisters, false);
     liveInV = bb->dataFlowInfo->liveInV =
-        dvmCompilerAllocBitVector(cUnit->method->registersSize, false);
+        dvmCompilerAllocBitVector(cUnit->numDalvikRegisters, false);
 
     for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
         int dfAttributes =
@@ -972,12 +1141,13 @@ void dvmCompilerFindLiveIn(CompilationUnit *cUnit, BasicBlock *bb)
             }
         }
         if (dfAttributes & DF_HAS_DEFS) {
-            handleLiveInDef(defV, dInsn->vA);
+            handleDef(defV, dInsn->vA);
             if (dfAttributes & DF_DA_WIDE) {
-                handleLiveInDef(defV, dInsn->vA+1);
+                handleDef(defV, dInsn->vA+1);
             }
         }
     }
+    return true;
 }
 
 /* Find out the latest SSA register for a given Dalvik register */
@@ -1002,7 +1172,7 @@ static void handleSSADef(CompilationUnit *cUnit, int *defs, int dalvikReg,
     cUnit->dalvikToSSAMap[dalvikReg] = newD2SMapping;
 
     int newS2DMapping = ENCODE_REG_SUB(dalvikReg, dalvikSub);
-    dvmInsertGrowableList(cUnit->ssaToDalvikMap, (void *) newS2DMapping);
+    dvmInsertGrowableList(cUnit->ssaToDalvikMap, newS2DMapping);
 
     defs[regIndex] = ssaReg;
 }
@@ -1038,13 +1208,11 @@ static void dataFlowSSAFormat3RC(CompilationUnit *cUnit, MIR *mir)
 }
 
 /* Entry function to convert a block into SSA representation */
-void dvmCompilerDoSSAConversion(CompilationUnit *cUnit, BasicBlock *bb)
+bool dvmCompilerDoSSAConversion(CompilationUnit *cUnit, BasicBlock *bb)
 {
     MIR *mir;
 
-    if (bb->blockType != kDalvikByteCode && bb->blockType != kTraceEntryBlock) {
-        return;
-    }
+    if (bb->dataFlowInfo == NULL) return false;
 
     for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
         mir->ssaRep = (struct SSARepresentation *)
@@ -1150,13 +1318,18 @@ void dvmCompilerDoSSAConversion(CompilationUnit *cUnit, BasicBlock *bb)
         }
     }
 
+    /*
+     * Take a snapshot of Dalvik->SSA mapping at the end of each block. The
+     * input to PHI nodes can be derived from the snapshot of all predecessor
+     * blocks.
+     */
     bb->dataFlowInfo->dalvikToSSAMap =
         (int *)dvmCompilerNew(sizeof(int) * cUnit->method->registersSize,
                               false);
 
-    /* Take a snapshot of Dalvik->SSA mapping at the end of each block */
     memcpy(bb->dataFlowInfo->dalvikToSSAMap, cUnit->dalvikToSSAMap,
            sizeof(int) * cUnit->method->registersSize);
+    return true;
 }
 
 /* Setup a constant value for opcodes thare have the DF_SETS_CONST attribute */
@@ -1166,7 +1339,7 @@ static void setConstant(CompilationUnit *cUnit, int ssaReg, int value)
     cUnit->constantValues[ssaReg] = value;
 }
 
-void dvmCompilerDoConstantPropagation(CompilationUnit *cUnit, BasicBlock *bb)
+bool dvmCompilerDoConstantPropagation(CompilationUnit *cUnit, BasicBlock *bb)
 {
     MIR *mir;
     BitVector *isConstantV = cUnit->isConstantV;
@@ -1236,9 +1409,10 @@ void dvmCompilerDoConstantPropagation(CompilationUnit *cUnit, BasicBlock *bb)
         }
     }
     /* TODO: implement code to handle arithmetic operations */
+    return true;
 }
 
-void dvmCompilerFindInductionVariables(struct CompilationUnit *cUnit,
+bool dvmCompilerFindInductionVariables(struct CompilationUnit *cUnit,
                                        struct BasicBlock *bb)
 {
     BitVector *isIndVarV = cUnit->loopAnalysis->isIndVarV;
@@ -1248,13 +1422,13 @@ void dvmCompilerFindInductionVariables(struct CompilationUnit *cUnit,
 
     if (bb->blockType != kDalvikByteCode &&
         bb->blockType != kTraceEntryBlock) {
-        return;
+        return false;
     }
 
     /* If the bb doesn't have a phi it cannot contain an induction variable */
     if (bb->firstMIRInsn == NULL ||
         bb->firstMIRInsn->dalvikInsn.opcode != kMirOpPhi) {
-        return;
+        return false;
     }
 
     /* Find basic induction variable first */
@@ -1314,7 +1488,7 @@ void dvmCompilerFindInductionVariables(struct CompilationUnit *cUnit,
                     ivInfo->m = 1;         // always 1 to basic iv
                     ivInfo->c = 0;         // N/A to basic iv
                     ivInfo->inc = deltaValue;
-                    dvmInsertGrowableList(ivList, (void *) ivInfo);
+                    dvmInsertGrowableList(ivList, (intptr_t) ivInfo);
                     cUnit->loopAnalysis->numBasicIV++;
                     break;
                 }
@@ -1396,10 +1570,11 @@ void dvmCompilerFindInductionVariables(struct CompilationUnit *cUnit,
                 ivInfo->m = ivInfoOld->m;
                 ivInfo->c = c + ivInfoOld->c;
                 ivInfo->inc = ivInfoOld->inc;
-                dvmInsertGrowableList(ivList, (void *) ivInfo);
+                dvmInsertGrowableList(ivList, (intptr_t) ivInfo);
             }
         }
     }
+    return true;
 }
 
 /* Setup the basic data structures for SSA conversion */
@@ -1424,8 +1599,7 @@ void dvmInitializeSSAConversion(CompilationUnit *cUnit)
      * into "(0 << 16) | i"
      */
     for (i = 0; i < numDalvikReg; i++) {
-        dvmInsertGrowableList(cUnit->ssaToDalvikMap,
-                              (void *) ENCODE_REG_SUB(i, 0));
+        dvmInsertGrowableList(cUnit->ssaToDalvikMap, ENCODE_REG_SUB(i, 0));
     }
 
     /*
@@ -1442,10 +1616,17 @@ void dvmInitializeSSAConversion(CompilationUnit *cUnit)
     /*
      * Allocate the BasicBlockDataFlow structure for the entry and code blocks
      */
-    for (i = 0; i < cUnit->numBlocks; i++) {
-        BasicBlock *bb = cUnit->blockList[i];
+    GrowableListIterator iterator;
+
+    dvmGrowableListIteratorInit(&cUnit->blockList, &iterator);
+
+    while (true) {
+        BasicBlock *bb = (BasicBlock *) dvmGrowableListIteratorNext(&iterator);
+        if (bb == NULL) break;
         if (bb->blockType == kDalvikByteCode ||
-            bb->blockType == kTraceEntryBlock) {
+            bb->blockType == kTraceEntryBlock ||
+            bb->blockType == kMethodEntryBlock ||
+            bb->blockType == kMethodExitBlock) {
             bb->dataFlowInfo = (BasicBlockDataFlow *)
                 dvmCompilerNew(sizeof(BasicBlockDataFlow),
                                true);
@@ -1453,18 +1634,109 @@ void dvmInitializeSSAConversion(CompilationUnit *cUnit)
     }
 }
 
+/* Clear the visited flag for each BB */
+bool dvmCompilerClearVisitedFlag(struct CompilationUnit *cUnit,
+                                 struct BasicBlock *bb)
+{
+    bb->visited = false;
+    return true;
+}
+
 void dvmCompilerDataFlowAnalysisDispatcher(CompilationUnit *cUnit,
-                void (*func)(CompilationUnit *, BasicBlock *))
+                bool (*func)(CompilationUnit *, BasicBlock *),
+                DataFlowAnalysisMode dfaMode,
+                bool isIterative)
 {
-    int i;
-    for (i = 0; i < cUnit->numBlocks; i++) {
-        BasicBlock *bb = cUnit->blockList[i];
-        (*func)(cUnit, bb);
+    bool change = true;
+
+    while (change) {
+        change = false;
+
+        /* Scan all blocks and perform the operations specified in func */
+        if (dfaMode == kAllNodes) {
+            GrowableListIterator iterator;
+            dvmGrowableListIteratorInit(&cUnit->blockList, &iterator);
+            while (true) {
+                BasicBlock *bb =
+                    (BasicBlock *) dvmGrowableListIteratorNext(&iterator);
+                if (bb == NULL) break;
+                change |= (*func)(cUnit, bb);
+            }
+        }
+        /*
+         * Scan all reachable blocks and perform the operations specified in
+         * func.
+         */
+        else if (dfaMode == kReachableNodes) {
+            int numReachableBlocks = cUnit->numReachableBlocks;
+            int idx;
+            const GrowableList *blockList = &cUnit->blockList;
+
+            for (idx = 0; idx < numReachableBlocks; idx++) {
+                int blockIdx = cUnit->dfsOrder.elemList[idx];
+                BasicBlock *bb =
+                    (BasicBlock *) dvmGrowableListGetElement(blockList,
+                                                             blockIdx);
+                change |= (*func)(cUnit, bb);
+            }
+        }
+        /*
+         * Scan all reachable blocks by the pre-order in the depth-first-search
+         * CFG and perform the operations specified in func.
+         */
+        else if (dfaMode == kPreOrderDFSTraversal) {
+            int numReachableBlocks = cUnit->numReachableBlocks;
+            int idx;
+            const GrowableList *blockList = &cUnit->blockList;
+
+            for (idx = 0; idx < numReachableBlocks; idx++) {
+                int dfsIdx = cUnit->dfsOrder.elemList[idx];
+                BasicBlock *bb =
+                    (BasicBlock *) dvmGrowableListGetElement(blockList, dfsIdx);
+                change |= (*func)(cUnit, bb);
+            }
+        }
+        /*
+         * Scan all reachable blocks by the post-order in the depth-first-search
+         * CFG and perform the operations specified in func.
+         */
+        else if (dfaMode == kPostOrderDFSTraversal) {
+            int numReachableBlocks = cUnit->numReachableBlocks;
+            int idx;
+            const GrowableList *blockList = &cUnit->blockList;
+
+            for (idx = numReachableBlocks - 1; idx >= 0; idx--) {
+                int dfsIdx = cUnit->dfsOrder.elemList[idx];
+                BasicBlock *bb =
+                    (BasicBlock *) dvmGrowableListGetElement(blockList, dfsIdx);
+                change |= (*func)(cUnit, bb);
+            }
+        }
+        /*
+         * Scan all reachable blocks by the post-order in the dominator tree
+         * and perform the operations specified in func.
+         */
+        else if (dfaMode == kPostOrderDOMTraversal) {
+            int numReachableBlocks = cUnit->numReachableBlocks;
+            int idx;
+            const GrowableList *blockList = &cUnit->blockList;
+
+            for (idx = 0; idx < numReachableBlocks; idx++) {
+                int domIdx = cUnit->domPostOrderTraversal.elemList[idx];
+                BasicBlock *bb =
+                    (BasicBlock *) dvmGrowableListGetElement(blockList, domIdx);
+                change |= (*func)(cUnit, bb);
+            }
+        }
+        /* If isIterative is false, exit the loop after the first iteration */
+        change &= isIterative;
     }
 }
 
 /* Main entry point to do SSA conversion for non-loop traces */
 void dvmCompilerNonLoopAnalysis(CompilationUnit *cUnit)
 {
-    dvmCompilerDataFlowAnalysisDispatcher(cUnit, dvmCompilerDoSSAConversion);
+    dvmCompilerDataFlowAnalysisDispatcher(cUnit, dvmCompilerDoSSAConversion,
+                                          kAllNodes,
+                                          false /* isIterative */);
 }
index 76783ae..ab04215 100644 (file)
 
 #include "Dalvik.h"
 #include "libdex/DexOpcodes.h"
+#include "libdex/DexCatch.h"
 #include "interp/Jit.h"
 #include "CompilerInternals.h"
 #include "Dataflow.h"
 
+static inline bool contentIsInsn(const u2 *codePtr) {
+    u2 instr = *codePtr;
+    Opcode opcode = instr & 0xff;
+
+    /*
+     * Since the low 8-bit in metadata may look like OP_NOP, we need to check
+     * both the low and whole sub-word to determine whether it is code or data.
+     */
+    return (opcode != OP_NOP || instr == 0);
+}
+
 /*
  * Parse an instruction, return the length of the instruction
  */
 static inline int parseInsn(const u2 *codePtr, DecodedInstruction *decInsn,
                             bool printMe)
 {
-    u2 instr = *codePtr;
-    Opcode opcode = dexOpcodeFromCodeUnit(instr);
-    int insnWidth;
-
     // Don't parse instruction data
-    if (opcode == OP_NOP && instr != 0) {
+    if (!contentIsInsn(codePtr)) {
         return 0;
-    } else {
-        insnWidth = dexGetWidthFromOpcode(opcode);
-        if (insnWidth < 0) {
-            insnWidth = -insnWidth;
-        }
     }
 
+    u2 instr = *codePtr;
+    Opcode opcode = dexOpcodeFromCodeUnit(instr);
+
     dexDecodeInstruction(codePtr, decInsn);
     if (printMe) {
         char *decodedString = dvmCompilerGetDalvikDisassembly(decInsn, NULL);
         LOGD("%p: %#06x %s\n", codePtr, opcode, decodedString);
     }
-    return insnWidth;
+    return dexGetWidthFromOpcode(opcode);
 }
 
 #define UNKNOWN_TARGET 0xffffffff
@@ -419,10 +425,11 @@ bool dvmCompileTrace(JitTraceDescription *desc, int numMaxInsts,
     const u2 *codePtr = dexCode->insns + curOffset;
     int traceSize = 0;  // # of half-words
     const u2 *startCodePtr = codePtr;
-    BasicBlock *startBB, *curBB, *lastBB;
+    BasicBlock *curBB, *entryCodeBB;
     int numBlocks = 0;
     static int compilationId;
     CompilationUnit cUnit;
+    GrowableList *blockList;
 #if defined(WITH_JIT_TUNING)
     CompilerMethodStats *methodStats;
 #endif
@@ -460,6 +467,10 @@ bool dvmCompileTrace(JitTraceDescription *desc, int numMaxInsts,
     /* Initialize the PC reconstruction list */
     dvmInitGrowableList(&cUnit.pcReconstructionList, 8);
 
+    /* Initialize the basic block list */
+    blockList = &cUnit.blockList;
+    dvmInitGrowableList(blockList, 8);
+
     /* Identify traces that we don't want to compile */
     if (gDvmJit.methodTable) {
         int len = strlen(desc->method->clazz->descriptor) +
@@ -534,18 +545,15 @@ bool dvmCompileTrace(JitTraceDescription *desc, int numMaxInsts,
     }
 
     /* Allocate the entry block */
-    lastBB = startBB = curBB = dvmCompilerNewBB(kTraceEntryBlock);
-    curBB->startOffset = curOffset;
-    curBB->id = numBlocks++;
-
-    curBB = dvmCompilerNewBB(kDalvikByteCode);
+    curBB = dvmCompilerNewBB(kTraceEntryBlock, numBlocks++);
+    dvmInsertGrowableList(blockList, (intptr_t) curBB);
     curBB->startOffset = curOffset;
-    curBB->id = numBlocks++;
 
-    /* Make the first real dalvik block the fallthrough of the entry block */
-    startBB->fallThrough = curBB;
-    lastBB->next = curBB;
-    lastBB = curBB;
+    entryCodeBB = dvmCompilerNewBB(kDalvikByteCode, numBlocks++);
+    dvmInsertGrowableList(blockList, (intptr_t) entryCodeBB);
+    entryCodeBB->startOffset = curOffset;
+    curBB->fallThrough = entryCodeBB;
+    curBB = entryCodeBB;
 
     if (cUnit.printMe) {
         LOGD("--------\nCompiler: Building trace for %s, offset 0x%x\n",
@@ -599,10 +607,8 @@ bool dvmCompileTrace(JitTraceDescription *desc, int numMaxInsts,
                     break;
                 }
 
-                curBB = dvmCompilerNewBB(kDalvikByteCode);
-                lastBB->next = curBB;
-                lastBB = curBB;
-                curBB->id = numBlocks++;
+                curBB = dvmCompilerNewBB(kDalvikByteCode, numBlocks++);
+                dvmInsertGrowableList(blockList, (intptr_t) curBB);
                 curOffset = currRun->frag.startOffset;
                 numInsts = currRun->frag.numInsts;
                 curBB->startOffset = curOffset;
@@ -624,7 +630,9 @@ bool dvmCompileTrace(JitTraceDescription *desc, int numMaxInsts,
      * taken/fallthrough links. Also create chaining cells for code not included
      * in the trace.
      */
-    for (curBB = startBB; curBB; curBB = curBB->next) {
+    size_t blockId;
+    for (blockId = 0; blockId < blockList->numUsed; blockId++) {
+        curBB = (BasicBlock *) dvmGrowableListGetElement(blockList, blockId);
         MIR *lastInsn = curBB->lastMIRInsn;
         /* Skip empty blocks */
         if (lastInsn == NULL) {
@@ -649,7 +657,11 @@ bool dvmCompileTrace(JitTraceDescription *desc, int numMaxInsts,
         }
 
         /* No backward branch in the trace - start searching the next BB */
-        for (searchBB = curBB->next; searchBB; searchBB = searchBB->next) {
+        size_t searchBlockId;
+        for (searchBlockId = blockId+1; searchBlockId < blockList->numUsed;
+             searchBlockId++) {
+            searchBB = (BasicBlock *) dvmGrowableListGetElement(blockList,
+                                                                searchBlockId);
             if (targetOffset == searchBB->startOffset) {
                 curBB->taken = searchBB;
             }
@@ -681,7 +693,7 @@ bool dvmCompileTrace(JitTraceDescription *desc, int numMaxInsts,
         if (curBB->taken == NULL &&
             curBB->fallThrough == NULL &&
             flags == (kInstrCanBranch | kInstrCanContinue) &&
-            fallThroughOffset == startBB->startOffset &&
+            fallThroughOffset == entryCodeBB->startOffset &&
             JIT_OPT_NO_LOOP != (optHints & JIT_OPT_NO_LOOP)) {
             BasicBlock *loopBranch = curBB;
             BasicBlock *exitBB;
@@ -690,48 +702,37 @@ bool dvmCompileTrace(JitTraceDescription *desc, int numMaxInsts,
             if (cUnit.printMe) {
                 LOGD("Natural loop detected!");
             }
-            exitBB = dvmCompilerNewBB(kTraceExitBlock);
-            lastBB->next = exitBB;
-            lastBB = exitBB;
-
+            exitBB = dvmCompilerNewBB(kTraceExitBlock, numBlocks++);
+            dvmInsertGrowableList(blockList, (intptr_t) exitBB);
             exitBB->startOffset = targetOffset;
-            exitBB->id = numBlocks++;
             exitBB->needFallThroughBranch = true;
 
             loopBranch->taken = exitBB;
 #if defined(WITH_SELF_VERIFICATION)
             BasicBlock *backwardCell =
-                dvmCompilerNewBB(kChainingCellBackwardBranch);
-            lastBB->next = backwardCell;
-            lastBB = backwardCell;
-
-            backwardCell->startOffset = startBB->startOffset;
-            backwardCell->id = numBlocks++;
+                dvmCompilerNewBB(kChainingCellBackwardBranch, numBlocks++);
+            dvmInsertGrowableList(blockList, (intptr_t) backwardCell);
+            backwardCell->startOffset = entryCodeBB->startOffset;
             loopBranch->fallThrough = backwardCell;
 #elif defined(WITH_JIT_TUNING)
             if (gDvmJit.profile) {
                 BasicBlock *backwardCell =
-                    dvmCompilerNewBB(kChainingCellBackwardBranch);
-                lastBB->next = backwardCell;
-                lastBB = backwardCell;
-
-                backwardCell->startOffset = startBB->startOffset;
-                backwardCell->id = numBlocks++;
+                    dvmCompilerNewBB(kChainingCellBackwardBranch, numBlocks++);
+                dvmInsertGrowableList(blockList, (intptr_t) backwardCell);
+                backwardCell->startOffset = entryCodeBB->startOffset;
                 loopBranch->fallThrough = backwardCell;
             } else {
-                loopBranch->fallThrough = startBB->next;
+                loopBranch->fallThrough = entryCodeBB;
             }
 #else
-            loopBranch->fallThrough = startBB->next;
+            loopBranch->fallThrough = entryCodeBB;
 #endif
 
             /* Create the chaining cell as the fallthrough of the exit block */
-            exitChainingCell = dvmCompilerNewBB(kChainingCellNormal);
-            lastBB->next = exitChainingCell;
-            lastBB = exitChainingCell;
-
+            exitChainingCell = dvmCompilerNewBB(kChainingCellNormal,
+                                                numBlocks++);
+            dvmInsertGrowableList(blockList, (intptr_t) exitChainingCell);
             exitChainingCell->startOffset = targetOffset;
-            exitChainingCell->id = numBlocks++;
 
             exitBB->fallThrough = exitChainingCell;
 
@@ -762,38 +763,35 @@ bool dvmCompileTrace(JitTraceDescription *desc, int numMaxInsts,
 
             /* One chaining cell for the first MAX_CHAINED_SWITCH_CASES cases */
             for (i = 0; i < maxChains; i++) {
-                BasicBlock *caseChain = dvmCompilerNewBB(kChainingCellNormal);
-                lastBB->next = caseChain;
-                lastBB = caseChain;
-
+                BasicBlock *caseChain = dvmCompilerNewBB(kChainingCellNormal,
+                                                         numBlocks++);
+                dvmInsertGrowableList(blockList, (intptr_t) caseChain);
                 caseChain->startOffset = lastInsn->offset + targets[i];
-                caseChain->id = numBlocks++;
             }
 
             /* One more chaining cell for the default case */
-            BasicBlock *caseChain = dvmCompilerNewBB(kChainingCellNormal);
-            lastBB->next = caseChain;
-            lastBB = caseChain;
-
+            BasicBlock *caseChain = dvmCompilerNewBB(kChainingCellNormal,
+                                                     numBlocks++);
+            dvmInsertGrowableList(blockList, (intptr_t) caseChain);
             caseChain->startOffset = lastInsn->offset + lastInsn->width;
-            caseChain->id = numBlocks++;
         /* Fallthrough block not included in the trace */
         } else if (!isUnconditionalBranch(lastInsn) &&
                    curBB->fallThrough == NULL) {
+            BasicBlock *fallThroughBB;
             /*
              * If the chaining cell is after an invoke or
              * instruction that cannot change the control flow, request a hot
              * chaining cell.
              */
             if (isInvoke || curBB->needFallThroughBranch) {
-                lastBB->next = dvmCompilerNewBB(kChainingCellHot);
+                fallThroughBB = dvmCompilerNewBB(kChainingCellHot, numBlocks++);
             } else {
-                lastBB->next = dvmCompilerNewBB(kChainingCellNormal);
+                fallThroughBB = dvmCompilerNewBB(kChainingCellNormal,
+                                                 numBlocks++);
             }
-            lastBB = lastBB->next;
-            lastBB->id = numBlocks++;
-            lastBB->startOffset = fallThroughOffset;
-            curBB->fallThrough = lastBB;
+            dvmInsertGrowableList(blockList, (intptr_t) fallThroughBB);
+            fallThroughBB->startOffset = fallThroughOffset;
+            curBB->fallThrough = fallThroughBB;
         }
         /* Target block not included in the trace */
         if (curBB->taken == NULL &&
@@ -803,12 +801,14 @@ bool dvmCompileTrace(JitTraceDescription *desc, int numMaxInsts,
             if (isInvoke) {
                 /* Monomorphic callee */
                 if (callee) {
-                    newBB = dvmCompilerNewBB(kChainingCellInvokeSingleton);
+                    newBB = dvmCompilerNewBB(kChainingCellInvokeSingleton,
+                                             numBlocks++);
                     newBB->startOffset = 0;
                     newBB->containingMethod = callee;
                 /* Will resolve at runtime */
                 } else {
-                    newBB = dvmCompilerNewBB(kChainingCellInvokePredicted);
+                    newBB = dvmCompilerNewBB(kChainingCellInvokePredicted,
+                                             numBlocks++);
                     newBB->startOffset = 0;
                 }
             /* For unconditional branches, request a hot chaining cell */
@@ -816,40 +816,40 @@ bool dvmCompileTrace(JitTraceDescription *desc, int numMaxInsts,
 #if !defined(WITH_SELF_VERIFICATION)
                 newBB = dvmCompilerNewBB(dexIsGoto(flags) ?
                                                   kChainingCellHot :
-                                                  kChainingCellNormal);
+                                                  kChainingCellNormal,
+                                         numBlocks++);
                 newBB->startOffset = targetOffset;
 #else
                 /* Handle branches that branch back into the block */
                 if (targetOffset >= curBB->firstMIRInsn->offset &&
                     targetOffset <= curBB->lastMIRInsn->offset) {
-                    newBB = dvmCompilerNewBB(kChainingCellBackwardBranch);
+                    newBB = dvmCompilerNewBB(kChainingCellBackwardBranch,
+                                             numBlocks++);
                 } else {
                     newBB = dvmCompilerNewBB(dexIsGoto(flags) ?
                                                       kChainingCellHot :
-                                                      kChainingCellNormal);
+                                                      kChainingCellNormal,
+                                             numBlocks++);
                 }
                 newBB->startOffset = targetOffset;
 #endif
             }
-            newBB->id = numBlocks++;
             curBB->taken = newBB;
-            lastBB->next = newBB;
-            lastBB = newBB;
+            dvmInsertGrowableList(blockList, (intptr_t) newBB);
         }
     }
 
     /* Now create a special block to host PC reconstruction code */
-    lastBB->next = dvmCompilerNewBB(kPCReconstruction);
-    lastBB = lastBB->next;
-    lastBB->id = numBlocks++;
+    curBB = dvmCompilerNewBB(kPCReconstruction, numBlocks++);
+    dvmInsertGrowableList(blockList, (intptr_t) curBB);
 
     /* And one final block that publishes the PC and raise the exception */
-    lastBB->next = dvmCompilerNewBB(kExceptionHandling);
-    lastBB = lastBB->next;
-    lastBB->id = numBlocks++;
+    curBB = dvmCompilerNewBB(kExceptionHandling, numBlocks++);
+    dvmInsertGrowableList(blockList, (intptr_t) curBB);
 
     if (cUnit.printMe) {
-        char* signature = dexProtoCopyMethodDescriptor(&desc->method->prototype);
+        char* signature =
+            dexProtoCopyMethodDescriptor(&desc->method->prototype);
         LOGD("TRACEINFO (%d): 0x%08x %s%s.%s 0x%x %d of %d, %d blocks",
             compilationId,
             (intptr_t) desc->method->insns,
@@ -863,21 +863,8 @@ bool dvmCompileTrace(JitTraceDescription *desc, int numMaxInsts,
         free(signature);
     }
 
-    BasicBlock **blockList;
-
     cUnit.traceDesc = desc;
     cUnit.numBlocks = numBlocks;
-    blockList = cUnit.blockList =
-        (BasicBlock **)dvmCompilerNew(sizeof(BasicBlock *) * numBlocks, true);
-
-    int i;
-
-    for (i = 0, curBB = startBB; i < numBlocks; i++) {
-        blockList[i] = curBB;
-        curBB = curBB->next;
-    }
-    /* Make sure all blocks are added to the cUnit */
-    assert(curBB == NULL);
 
     /* Set the instruction set to use (NOTE: later components may change it) */
     cUnit.instructionSet = dvmCompilerInstructionSet();
@@ -887,6 +874,8 @@ bool dvmCompileTrace(JitTraceDescription *desc, int numMaxInsts,
         dvmCompilerInlineMIR(&cUnit);
     }
 
+    cUnit.numDalvikRegisters = cUnit.method->registersSize;
+
     /* Preparation for SSA conversion */
     dvmInitializeSSAConversion(&cUnit);
 
@@ -952,6 +941,15 @@ bool dvmCompileTrace(JitTraceDescription *desc, int numMaxInsts,
 #if defined(WITH_JIT_TUNING)
     methodStats->nativeSize += cUnit.totalSize;
 #endif
+
+    /* FIXME - to exercise the method parser, uncomment the following code */
+#if 0
+    bool dvmCompileMethod(const Method *method);
+    if (desc->trace[0].frag.startOffset == 0) {
+        dvmCompileMethod(desc->method);
+    }
+#endif
+
     return info->codeAddress != NULL;
 }
 
@@ -1053,255 +1051,730 @@ bool dvmCompilerCanIncludeThisInstruction(const Method *method,
     }
 }
 
-/*
- * Similar to dvmCompileTrace, but the entity processed here is the whole
- * method.
- *
- * TODO: implementation will be revisited when the trace builder can provide
- * whole-method traces.
- */
-bool dvmCompileMethod(CompilationUnit *cUnit, const Method *method,
-                      JitTranslationInfo *info)
+/* Split an existing block from the specified code offset into two */
+static BasicBlock *splitBlock(CompilationUnit *cUnit,
+                              unsigned int codeOffset,
+                              BasicBlock *origBlock)
 {
-    const DexCode *dexCode = dvmGetMethodCode(method);
-    const u2 *codePtr = dexCode->insns;
-    const u2 *codeEnd = dexCode->insns + dexCode->insnsSize;
-    int blockID = 0;
-    unsigned int curOffset = 0;
+    MIR *insn = origBlock->firstMIRInsn;
+    while (insn) {
+        if (insn->offset == codeOffset) break;
+        insn = insn->next;
+    }
+    if (insn == NULL) {
+        LOGE("Break split failed");
+        dvmAbort();
+    }
+    BasicBlock *bottomBlock = dvmCompilerNewBB(kDalvikByteCode,
+                                               cUnit->numBlocks++);
+    dvmInsertGrowableList(&cUnit->blockList, (intptr_t) bottomBlock);
+
+    bottomBlock->startOffset = codeOffset;
+    bottomBlock->firstMIRInsn = insn;
+    bottomBlock->lastMIRInsn = origBlock->lastMIRInsn;
+
+    /* Only the top half of split blocks is tagged as BA_CATCH_BLOCK */
+    bottomBlock->blockAttributes = origBlock->blockAttributes & ~BA_CATCH_BLOCK;
+
+    /* Handle the taken path */
+    bottomBlock->taken = origBlock->taken;
+    if (bottomBlock->taken) {
+        origBlock->taken = NULL;
+        dvmCompilerClearBit(bottomBlock->taken->predecessors, origBlock->id);
+        dvmCompilerSetBit(bottomBlock->taken->predecessors, bottomBlock->id);
+    }
 
-    /* If we've already compiled this trace, just return success */
-    if (dvmJitGetCodeAddr(codePtr) && !info->discardResult) {
-        return true;
+    /* Handle the fallthrough path */
+    bottomBlock->fallThrough = origBlock->fallThrough;
+    origBlock->fallThrough = bottomBlock;
+    dvmCompilerSetBit(bottomBlock->predecessors, origBlock->id);
+    if (bottomBlock->fallThrough) {
+        dvmCompilerClearBit(bottomBlock->fallThrough->predecessors,
+                            origBlock->id);
+        dvmCompilerSetBit(bottomBlock->fallThrough->predecessors,
+                          bottomBlock->id);
+    }
+
+    /* Handle the successor list */
+    if (origBlock->successorBlockList.blockListType != kNotUsed) {
+        bottomBlock->successorBlockList = origBlock->successorBlockList;
+        origBlock->successorBlockList.blockListType = kNotUsed;
+        GrowableListIterator iterator;
+
+        dvmGrowableListIteratorInit(&bottomBlock->successorBlockList.blocks,
+                                    &iterator);
+        while (true) {
+            BasicBlock *bb =
+                (BasicBlock *) dvmGrowableListIteratorNext(&iterator);
+            if (bb == NULL) break;
+            dvmCompilerClearBit(bb->predecessors, origBlock->id);
+            dvmCompilerSetBit(bb->predecessors, bottomBlock->id);
+        }
     }
 
-    /* Doing method-based compilation */
-    cUnit->wholeMethod = true;
+    origBlock->lastMIRInsn = insn->prev;
+    /* Only the bottom half of split blocks is tagged as BA_ENDS_WITH_THROW */
+    origBlock->blockAttributes &= ~BA_ENDS_WITH_THROW;
 
-    BasicBlock *firstBlock = dvmCompilerNewBB(kDalvikByteCode);
-    firstBlock->id = blockID++;
+    insn->prev->next = NULL;
+    insn->prev = NULL;
+    return bottomBlock;
+}
 
-    /* Allocate the bit-vector to track the beginning of basic blocks */
-    BitVector *bbStartAddr = dvmCompilerAllocBitVector(dexCode->insnsSize+1,
-                                                       false);
-    dvmCompilerSetBit(bbStartAddr, 0);
+/*
+ * Given a code offset, find out the block that starts with it. If the offset
+ * is in the middle of an existing block, split it into two.
+ */
+static BasicBlock *findBlock(CompilationUnit *cUnit,
+                             unsigned int codeOffset,
+                             bool split, bool create)
+{
+    GrowableList *blockList = &cUnit->blockList;
+    BasicBlock *bb;
+    unsigned int i;
+
+    for (i = 0; i < blockList->numUsed; i++) {
+        bb = (BasicBlock *) blockList->elemList[i];
+        if (bb->blockType != kDalvikByteCode) continue;
+        if (bb->startOffset == codeOffset) return bb;
+        /* Check if a branch jumps into the middle of an existing block */
+        if ((split == true) && (codeOffset > bb->startOffset) &&
+            (bb->lastMIRInsn != NULL) &&
+            (codeOffset <= bb->lastMIRInsn->offset)) {
+            BasicBlock *newBB = splitBlock(cUnit, codeOffset, bb);
+            return newBB;
+        }
+    }
+    if (create) {
+          bb = dvmCompilerNewBB(kDalvikByteCode, cUnit->numBlocks++);
+          dvmInsertGrowableList(&cUnit->blockList, (intptr_t) bb);
+          bb->startOffset = codeOffset;
+          return bb;
+    }
+    return NULL;
+}
 
-    int numInvokeTargets = 0;
+/* Dump the CFG into a DOT graph */
+void dumpCFG(CompilationUnit *cUnit, const char *dirPrefix)
+{
+    const Method *method = cUnit->method;
+    FILE *file;
+    char* signature = dexProtoCopyMethodDescriptor(&method->prototype);
+    char *fileName = (char *) dvmCompilerNew(
+                                  strlen(dirPrefix) +
+                                  strlen(method->clazz->descriptor) +
+                                  strlen(method->name) +
+                                  strlen(signature) +
+                                  strlen(".dot") + 1, true);
+    sprintf(fileName, "%s%s%s%s.dot", dirPrefix,
+            method->clazz->descriptor, method->name, signature);
+    free(signature);
 
     /*
-     * Sequentially go through every instruction first and put them in a single
-     * basic block. Identify block boundaries at the mean time.
+     * Convert the special characters into a filesystem- and shell-friendly
+     * format.
      */
-    while (codePtr < codeEnd) {
-        MIR *insn = (MIR *)dvmCompilerNew(sizeof(MIR), true);
-        insn->offset = curOffset;
-        int width = parseInsn(codePtr, &insn->dalvikInsn, false);
-        bool isInvoke = false;
-        const Method *callee;
-        insn->width = width;
+    int i;
+    for (i = strlen(dirPrefix); fileName[i]; i++) {
+        if (fileName[i] == '/') {
+            fileName[i] = '_';
+        } else if (fileName[i] == ';') {
+            fileName[i] = '#';
+        } else if (fileName[i] == '$') {
+            fileName[i] = '+';
+        } else if (fileName[i] == '(' || fileName[i] == ')') {
+            fileName[i] = '@';
+        } else if (fileName[i] == '<' || fileName[i] == '>') {
+            fileName[i] = '=';
+        }
+    }
+    file = fopen(fileName, "w");
+    if (file == NULL) {
+        return;
+    }
+    fprintf(file, "digraph G {\n");
+
+    fprintf(file, "  rankdir=TB\n");
+
+    int numReachableBlocks = cUnit->numReachableBlocks;
+    int idx;
+    const GrowableList *blockList = &cUnit->blockList;
+
+    for (idx = 0; idx < numReachableBlocks; idx++) {
+        int blockIdx = cUnit->dfsOrder.elemList[idx];
+        BasicBlock *bb = (BasicBlock *) dvmGrowableListGetElement(blockList,
+                                                                  blockIdx);
+        if (bb == NULL) break;
+        if (bb->blockType == kMethodEntryBlock) {
+            fprintf(file, "  entry [shape=Mdiamond];\n");
+        } else if (bb->blockType == kMethodExitBlock) {
+            fprintf(file, "  exit [shape=Mdiamond];\n");
+        } else if (bb->blockType == kDalvikByteCode) {
+            fprintf(file, "  block%04x [shape=%s,label = \"{ \\\n",
+                    bb->startOffset,
+                    bb->blockAttributes & BA_CATCH_BLOCK ?
+                      "Mrecord" : "record");
+            if (bb->blockAttributes & BA_CATCH_BLOCK) {
+                if (bb->exceptionTypeIdx == kDexNoIndex) {
+                    fprintf(file, "    {any\\l} |\\\n");
+                } else {
+                    fprintf(file, "    {throwable type:%x\\l} |\\\n",
+                            bb->exceptionTypeIdx);
+                }
+            }
+            const MIR *mir;
+            for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
+                fprintf(file, "    {%04x %s\\l}%s\\\n", mir->offset,
+                        dvmCompilerFullDisassembler(cUnit, mir),
+                        mir->next ? " | " : " ");
+            }
+            fprintf(file, "  }\"];\n\n");
+        } else if (bb->blockType == kExceptionHandling) {
+            char blockName[BLOCK_NAME_LEN];
 
-        /* Terminate when the data section is seen */
-        if (width == 0)
-            break;
+            dvmGetBlockName(bb, blockName);
+            fprintf(file, "  %s [shape=invhouse];\n", blockName);
+        }
 
-        if (!dvmCompilerCanIncludeThisInstruction(cUnit->method,
-                                                 &insn->dalvikInsn)) {
-            return false;
+        char blockName1[BLOCK_NAME_LEN], blockName2[BLOCK_NAME_LEN];
+
+        if (bb->taken) {
+            dvmGetBlockName(bb, blockName1);
+            dvmGetBlockName(bb->taken, blockName2);
+            fprintf(file, "  %s:s -> %s:n [style=dotted]\n",
+                    blockName1, blockName2);
+        }
+        if (bb->fallThrough) {
+            dvmGetBlockName(bb, blockName1);
+            dvmGetBlockName(bb->fallThrough, blockName2);
+            fprintf(file, "  %s:s -> %s:n\n", blockName1, blockName2);
         }
 
-        dvmCompilerAppendMIR(firstBlock, insn);
-        /*
-         * Check whether this is a block ending instruction and whether it
-         * suggests the start of a new block
-         */
-        unsigned int target = curOffset;
+        if (bb->successorBlockList.blockListType != kNotUsed) {
+            fprintf(file, "  succ%04x [shape=%s,label = \"{ \\\n",
+                    bb->startOffset,
+                    (bb->successorBlockList.blockListType == kCatch) ?
+                        "Mrecord" : "record");
+            GrowableListIterator iterator;
+            dvmGrowableListIteratorInit(&bb->successorBlockList.blocks,
+                                        &iterator);
+
+            BasicBlock *destBlock =
+                (BasicBlock *) dvmGrowableListIteratorNext(&iterator);
+
+            int succId = 0;
+            while (true) {
+                if (destBlock == NULL) break;
+                BasicBlock *nextBlock =
+                    (BasicBlock *) dvmGrowableListIteratorNext(&iterator);
+                fprintf(file, "    {<f%d> %04x\\l}%s\\\n",
+                        succId++,
+                        destBlock->startOffset,
+                        (nextBlock != NULL) ? " | " : " ");
+                destBlock = nextBlock;
+            }
+            fprintf(file, "  }\"];\n\n");
+
+            dvmGetBlockName(bb, blockName1);
+            fprintf(file, "  %s:s -> succ%04x:n [style=dashed]\n",
+                    blockName1, bb->startOffset);
+
+            if (bb->successorBlockList.blockListType == kPackedSwitch ||
+                bb->successorBlockList.blockListType == kSparseSwitch) {
+
+                dvmGrowableListIteratorInit(&bb->successorBlockList.blocks,
+                                            &iterator);
+
+                succId = 0;
+                while (true) {
+                    BasicBlock *destBlock =
+                        (BasicBlock *) dvmGrowableListIteratorNext(&iterator);
+                    if (destBlock == NULL) break;
+
+                    dvmGetBlockName(destBlock, blockName2);
+                    fprintf(file, "  succ%04x:f%d:e -> %s:n\n",
+                            bb->startOffset, succId++,
+                            blockName2);
+                }
+            }
+        }
+        fprintf(file, "\n");
 
         /*
-         * If findBlockBoundary returns true, it means the current instruction
-         * is terminating the current block. If it is a branch, the target
-         * address will be recorded in target.
+         * If we need to debug the dominator tree, uncomment the following code
          */
-        if (findBlockBoundary(method, insn, curOffset, &target, &isInvoke,
-                              &callee)) {
-            dvmCompilerSetBit(bbStartAddr, curOffset + width);
-            /* Each invoke needs a chaining cell block */
-            if (isInvoke) {
-                numInvokeTargets++;
-            }
-            /* A branch will end the current block */
-            else if (target != curOffset && target != UNKNOWN_TARGET) {
-                dvmCompilerSetBit(bbStartAddr, target);
+#if 0
+        dvmGetBlockName(bb, blockName1);
+        fprintf(file, "  cfg%s [label=\"%s\", shape=none];\n",
+                blockName1, blockName1);
+        if (bb->iDom) {
+            dvmGetBlockName(bb->iDom, blockName2);
+            fprintf(file, "  cfg%s:s -> cfg%s:n\n\n",
+                    blockName2, blockName1);
+        }
+#endif
+    }
+    fprintf(file, "}\n");
+    fclose(file);
+}
+
+/* Verify if all the successor is connected with all the claimed predecessors */
+static bool verifyPredInfo(CompilationUnit *cUnit, BasicBlock *bb)
+{
+    BitVectorIterator bvIterator;
+
+    dvmBitVectorIteratorInit(bb->predecessors, &bvIterator);
+    while (true) {
+        int blockIdx = dvmBitVectorIteratorNext(&bvIterator);
+        if (blockIdx == -1) break;
+        BasicBlock *predBB = (BasicBlock *)
+            dvmGrowableListGetElement(&cUnit->blockList, blockIdx);
+        bool found = false;
+        if (predBB->taken == bb) {
+            found = true;
+        } else if (predBB->fallThrough == bb) {
+            found = true;
+        } else if (predBB->successorBlockList.blockListType != kNotUsed) {
+            GrowableListIterator iterator;
+            dvmGrowableListIteratorInit(&predBB->successorBlockList.blocks,
+                                        &iterator);
+            while (true) {
+                BasicBlock *succBB =
+                    (BasicBlock *) dvmGrowableListIteratorNext(&iterator);
+                if (succBB == NULL) break;
+                if (succBB == bb) {
+                    found = true;
+                    break;
+                }
             }
         }
+        if (found == false) {
+            char blockName1[BLOCK_NAME_LEN], blockName2[BLOCK_NAME_LEN];
+            dvmGetBlockName(bb, blockName1);
+            dvmGetBlockName(predBB, blockName2);
+            dumpCFG(cUnit, "/data/tombstones/");
+            LOGE("Successor %s not found from %s",
+                 blockName1, blockName2);
+            dvmAbort();
+        }
+    }
+    return true;
+}
 
-        codePtr += width;
-        /* each bit represents 16-bit quantity */
-        curOffset += width;
+/* Identify code range in try blocks and set up the empty catch blocks */
+static void processTryCatchBlocks(CompilationUnit *cUnit)
+{
+    const Method *meth = cUnit->method;
+    const DexCode *pCode = dvmGetMethodCode(meth);
+    int triesSize = pCode->triesSize;
+    int i;
+    int offset;
+
+    if (triesSize == 0) {
+        return;
     }
 
-    /*
-     * The number of blocks will be equal to the number of bits set to 1 in the
-     * bit vector minus 1, because the bit representing the location after the
-     * last instruction is set to one.
-     *
-     * We also add additional blocks for invoke chaining and the number is
-     * denoted by numInvokeTargets.
-     */
-    int numBlocks = dvmCountSetBits(bbStartAddr);
-    if (dvmIsBitSet(bbStartAddr, dexCode->insnsSize)) {
-        numBlocks--;
+    const DexTry *pTries = dexGetTries(pCode);
+    BitVector *tryBlockAddr = cUnit->tryBlockAddr;
+
+    /* Mark all the insn offsets in Try blocks */
+    for (i = 0; i < triesSize; i++) {
+        const DexTry* pTry = &pTries[i];
+        /* all in 16-bit units */
+        int startOffset = pTry->startAddr;
+        int endOffset = startOffset + pTry->insnCount;
+
+        for (offset = startOffset; offset < endOffset; offset++) {
+            dvmCompilerSetBit(tryBlockAddr, offset);
+        }
     }
 
-    BasicBlock **blockList;
-    blockList = cUnit->blockList = (BasicBlock **)
-        dvmCompilerNew(sizeof(BasicBlock *) * (numBlocks + numInvokeTargets),
-                       true);
+    /* Iterate over each of the handlers to enqueue the empty Catch blocks */
+    offset = dexGetFirstHandlerOffset(pCode);
+    int handlersSize = dexGetHandlersSize(pCode);
 
-    /*
-     * Register the first block onto the list and start splitting it into
-     * sub-blocks.
-     */
-    blockList[0] = firstBlock;
-    cUnit->numBlocks = 1;
+    for (i = 0; i < handlersSize; i++) {
+        DexCatchIterator iterator;
+        dexCatchIteratorInit(&iterator, pCode, offset);
 
-    int i;
-    for (i = 0; i < numBlocks; i++) {
-        MIR *insn;
-        BasicBlock *curBB = blockList[i];
-        curOffset = curBB->lastMIRInsn->offset;
-
-        for (insn = curBB->firstMIRInsn->next; insn; insn = insn->next) {
-            /* Found the beginning of a new block, see if it is created yet */
-            if (dvmIsBitSet(bbStartAddr, insn->offset)) {
-                int j;
-                for (j = 0; j < cUnit->numBlocks; j++) {
-                    if (blockList[j]->firstMIRInsn->offset == insn->offset)
-                        break;
-                }
+        for (;;) {
+            DexCatchHandler* handler = dexCatchIteratorNext(&iterator);
 
-                /* Block not split yet - do it now */
-                if (j == cUnit->numBlocks) {
-                    BasicBlock *newBB = dvmCompilerNewBB(kDalvikByteCode);
-                    newBB->id = blockID++;
-                    newBB->firstMIRInsn = insn;
-                    newBB->startOffset = insn->offset;
-                    newBB->lastMIRInsn = curBB->lastMIRInsn;
-                    curBB->lastMIRInsn = insn->prev;
-                    insn->prev->next = NULL;
-                    insn->prev = NULL;
-
-                    /*
-                     * If the insn is not an unconditional branch, set up the
-                     * fallthrough link.
-                     */
-                    if (!isUnconditionalBranch(curBB->lastMIRInsn)) {
-                        curBB->fallThrough = newBB;
-                    }
-
-                    /*
-                     * Fallthrough block of an invoke instruction needs to be
-                     * aligned to 4-byte boundary (alignment instruction to be
-                     * inserted later.
-                     */
-                    if (dexGetFlagsFromOpcode(curBB->lastMIRInsn->dalvikInsn.opcode)
-                            & kInstrInvoke) {
-                        newBB->isFallThroughFromInvoke = true;
-                    }
-
-                    /* enqueue the new block */
-                    blockList[cUnit->numBlocks++] = newBB;
-                    break;
-                }
+            if (handler == NULL) {
+                break;
             }
+
+            BasicBlock *catchBlock = findBlock(cUnit, handler->address,
+                                               /* split */
+                                               false,
+                                               /* create */
+                                               true);
+            catchBlock->blockAttributes |= BA_CATCH_BLOCK;
+            catchBlock->exceptionTypeIdx = handler->typeIdx;
         }
+
+        offset = dexCatchIteratorGetEndOffset(&iterator, pCode);
     }
+}
 
-    if (numBlocks != cUnit->numBlocks) {
-        LOGE("Expect %d vs %d basic blocks\n", numBlocks, cUnit->numBlocks);
-        dvmCompilerAbort(cUnit);
+/* Process instructions with the kInstrCanBranch flag */
+static void processCanBranch(CompilationUnit *cUnit, BasicBlock *curBlock,
+                             MIR *insn, int curOffset, int width, int flags,
+                             const u2* codePtr, const u2* codeEnd)
+{
+    int target = curOffset;
+    switch (insn->dalvikInsn.opcode) {
+        case OP_GOTO:
+        case OP_GOTO_16:
+        case OP_GOTO_32:
+            target += (int) insn->dalvikInsn.vA;
+            break;
+        case OP_IF_EQ:
+        case OP_IF_NE:
+        case OP_IF_LT:
+        case OP_IF_GE:
+        case OP_IF_GT:
+        case OP_IF_LE:
+            target += (int) insn->dalvikInsn.vC;
+            break;
+        case OP_IF_EQZ:
+        case OP_IF_NEZ:
+        case OP_IF_LTZ:
+        case OP_IF_GEZ:
+        case OP_IF_GTZ:
+        case OP_IF_LEZ:
+            target += (int) insn->dalvikInsn.vB;
+            break;
+        default:
+            LOGE("Unexpected opcode(%d) with kInstrCanBranch set",
+                 insn->dalvikInsn.opcode);
+            dvmAbort();
     }
+    BasicBlock *takenBlock = findBlock(cUnit, target,
+                                       /* split */
+                                       true,
+                                       /* create */
+                                       true);
+    curBlock->taken = takenBlock;
+    dvmCompilerSetBit(takenBlock->predecessors, curBlock->id);
+
+    /* Always terminate the current block for conditional branches */
+    if (flags & kInstrCanContinue) {
+        BasicBlock *fallthroughBlock = findBlock(cUnit,
+                                                 curOffset +  width,
+                                                 /* split */
+                                                 false,
+                                                 /* create */
+                                                 true);
+        curBlock->fallThrough = fallthroughBlock;
+        dvmCompilerSetBit(fallthroughBlock->predecessors, curBlock->id);
+    } else if (codePtr < codeEnd) {
+        /* Create a fallthrough block for real instructions (incl. OP_NOP) */
+        if (contentIsInsn(codePtr)) {
+            findBlock(cUnit, curOffset + width,
+                      /* split */
+                      false,
+                      /* create */
+                      true);
+        }
+    }
+}
 
-    /* Connect the basic blocks through the taken links */
-    for (i = 0; i < numBlocks; i++) {
-        BasicBlock *curBB = blockList[i];
-        MIR *insn = curBB->lastMIRInsn;
-        unsigned int target = insn->offset;
-        bool isInvoke = false;
-        const Method *callee = NULL;
+/* Process instructions with the kInstrCanSwitch flag */
+static void processCanSwitch(CompilationUnit *cUnit, BasicBlock *curBlock,
+                             MIR *insn, int curOffset, int width, int flags)
+{
+    u2 *switchData= (u2 *) (cUnit->method->insns + curOffset +
+                            insn->dalvikInsn.vB);
+    int size;
+    int *targetTable;
+    int i;
+
+    /*
+     * Packed switch data format:
+     *  ushort ident = 0x0100   magic value
+     *  ushort size             number of entries in the table
+     *  int first_key           first (and lowest) switch case value
+     *  int targets[size]       branch targets, relative to switch opcode
+     *
+     * Total size is (4+size*2) 16-bit code units.
+     */
+    if (insn->dalvikInsn.opcode == OP_PACKED_SWITCH) {
+        assert(switchData[0] == kPackedSwitchSignature);
+        size = switchData[1];
+        targetTable = (int *) &switchData[4];
+    /*
+     * Sparse switch data format:
+     *  ushort ident = 0x0200   magic value
+     *  ushort size             number of entries in the table; > 0
+     *  int keys[size]          keys, sorted low-to-high; 32-bit aligned
+     *  int targets[size]       branch targets, relative to switch opcode
+     *
+     * Total size is (2+size*4) 16-bit code units.
+     */
+    } else {
+        assert(switchData[0] == kSparseSwitchSignature);
+        size = switchData[1];
+        targetTable = (int *) &switchData[2 + size*2];
+    }
 
-        findBlockBoundary(method, insn, target, &target, &isInvoke, &callee);
+    if (curBlock->successorBlockList.blockListType != kNotUsed) {
+        LOGE("Successor block list already in use: %d",
+             curBlock->successorBlockList.blockListType);
+        dvmAbort();
+    }
+    curBlock->successorBlockList.blockListType =
+        (insn->dalvikInsn.opcode == OP_PACKED_SWITCH) ?
+        kPackedSwitch : kSparseSwitch;
+    dvmInitGrowableList(&curBlock->successorBlockList.blocks, size);
+
+    for (i = 0; i < size; i++) {
+        BasicBlock *caseBlock = findBlock(cUnit, curOffset + targetTable[i],
+                                          /* split */
+                                          true,
+                                          /* create */
+                                          true);
+        dvmInsertGrowableList(&curBlock->successorBlockList.blocks,
+                              (intptr_t) caseBlock);
+        dvmCompilerSetBit(caseBlock->predecessors, curBlock->id);
+    }
+
+    /* Fall-through case */
+    BasicBlock *fallthroughBlock = findBlock(cUnit,
+                                             curOffset +  width,
+                                             /* split */
+                                             false,
+                                             /* create */
+                                             true);
+    curBlock->fallThrough = fallthroughBlock;
+    dvmCompilerSetBit(fallthroughBlock->predecessors, curBlock->id);
+}
+
+/* Process instructions with the kInstrCanThrow flag */
+static void processCanThrow(CompilationUnit *cUnit, BasicBlock *curBlock,
+                            MIR *insn, int curOffset, int width, int flags,
+                            BitVector *tryBlockAddr, const u2 *codePtr,
+                            const u2* codeEnd)
+{
+    const Method *method = cUnit->method;
+    const DexCode *dexCode = dvmGetMethodCode(method);
+
+    curBlock->blockAttributes |= BA_ENDS_WITH_THROW;
+    /* In try block */
+    if (dvmIsBitSet(tryBlockAddr, curOffset)) {
+        DexCatchIterator iterator;
+
+        if (!dexFindCatchHandler(&iterator, dexCode, curOffset)) {
+            LOGE("Catch block not found in dexfile for insn %x in %s",
+                 curOffset, method->name);
+            dvmAbort();
 
-        /* Found a block ended on a branch (not invoke) */
-        if (isInvoke == false && target != insn->offset) {
-            int j;
-            /* Forward branch */
-            if (target > insn->offset) {
-                j = i + 1;
-            } else {
-                /* Backward branch */
-                j = 0;
-            }
-            for (; j < numBlocks; j++) {
-                if (blockList[j]->firstMIRInsn->offset == target) {
-                    curBB->taken = blockList[j];
-                    break;
-                }
-            }
         }
+        if (curBlock->successorBlockList.blockListType != kNotUsed) {
+            LOGE("Successor block list already in use: %d",
+                 curBlock->successorBlockList.blockListType);
+            dvmAbort();
+        }
+        curBlock->successorBlockList.blockListType = kCatch;
+        dvmInitGrowableList(&curBlock->successorBlockList.blocks, 2);
 
-        if (isInvoke) {
-            BasicBlock *newBB;
-            /* Monomorphic callee */
-            if (callee) {
-                newBB = dvmCompilerNewBB(kChainingCellInvokeSingleton);
-                newBB->startOffset = 0;
-                newBB->containingMethod = callee;
-            /* Will resolve at runtime */
-            } else {
-                newBB = dvmCompilerNewBB(kChainingCellInvokePredicted);
-                newBB->startOffset = 0;
+        for (;;) {
+            DexCatchHandler* handler = dexCatchIteratorNext(&iterator);
+
+            if (handler == NULL) {
+                break;
             }
-            newBB->id = blockID++;
-            curBB->taken = newBB;
-            /* enqueue the new block */
-            blockList[cUnit->numBlocks++] = newBB;
+
+            BasicBlock *catchBlock = findBlock(cUnit, handler->address,
+                                               /* split */
+                                               false,
+                                               /* create */
+                                               false);
+
+            assert(catchBlock->blockAttributes & BA_CATCH_BLOCK);
+            dvmInsertGrowableList(&curBlock->successorBlockList.blocks,
+                                  (intptr_t) catchBlock);
+            dvmCompilerSetBit(catchBlock->predecessors, curBlock->id);
         }
+    } else {
+        BasicBlock *ehBlock = dvmCompilerNewBB(kExceptionHandling,
+                                               cUnit->numBlocks++);
+        curBlock->taken = ehBlock;
+        dvmInsertGrowableList(&cUnit->blockList, (intptr_t) ehBlock);
+        ehBlock->startOffset = curOffset;
+        dvmCompilerSetBit(ehBlock->predecessors, curBlock->id);
     }
 
-    if (cUnit->numBlocks != numBlocks + numInvokeTargets) {
-        LOGE("Expect %d vs %d total blocks\n", numBlocks + numInvokeTargets,
-             cUnit->numBlocks);
-        dvmCompilerDumpCompilationUnit(cUnit);
-        dvmCompilerAbort(cUnit);
+    /*
+     * Force the current block to terminate.
+     *
+     * Data may be present before codeEnd, so we need to parse it to know
+     * whether it is code or data.
+     */
+    if (codePtr < codeEnd) {
+        /* Create a fallthrough block for real instructions (incl. OP_NOP) */
+        if (contentIsInsn(codePtr)) {
+            BasicBlock *fallthroughBlock = findBlock(cUnit,
+                                                     curOffset + width,
+                                                     /* split */
+                                                     false,
+                                                     /* create */
+                                                     true);
+            /*
+             * OP_THROW and OP_THROW_VERIFICATION_ERROR are unconditional
+             * branches.
+             */
+            if (insn->dalvikInsn.opcode != OP_THROW_VERIFICATION_ERROR &&
+                insn->dalvikInsn.opcode != OP_THROW) {
+                curBlock->fallThrough = fallthroughBlock;
+                dvmCompilerSetBit(fallthroughBlock->predecessors, curBlock->id);
+            }
+        }
     }
+}
 
-    /* Set the instruction set to use (NOTE: later components may change it) */
-    cUnit->instructionSet = dvmCompilerInstructionSet();
+/*
+ * Similar to dvmCompileTrace, but the entity processed here is the whole
+ * method.
+ *
+ * TODO: implementation will be revisited when the trace builder can provide
+ * whole-method traces.
+ */
+bool dvmCompileMethod(const Method *method)
+{
+    CompilationUnit cUnit;
+    const DexCode *dexCode = dvmGetMethodCode(method);
+    const u2 *codePtr = dexCode->insns;
+    const u2 *codeEnd = dexCode->insns + dexCode->insnsSize;
+    int numBlocks = 0;
+    unsigned int curOffset = 0;
 
-    /* Preparation for SSA conversion */
-    dvmInitializeSSAConversion(cUnit);
+    memset(&cUnit, 0, sizeof(cUnit));
+    cUnit.method = method;
+
+    /* Initialize the block list */
+    dvmInitGrowableList(&cUnit.blockList, 4);
 
-    /* SSA analysis */
-    dvmCompilerNonLoopAnalysis(cUnit);
+    /* Allocate the bit-vector to track the beginning of basic blocks */
+    BitVector *tryBlockAddr = dvmCompilerAllocBitVector(dexCode->insnsSize,
+                                                        true /* expandable */);
+    cUnit.tryBlockAddr = tryBlockAddr;
 
-    /* Needs to happen after SSA naming */
-    dvmCompilerInitializeRegAlloc(cUnit);
+    /* Create the default entry and exit blocks and enter them to the list */
+    BasicBlock *entryBlock = dvmCompilerNewBB(kMethodEntryBlock, numBlocks++);
+    BasicBlock *exitBlock = dvmCompilerNewBB(kMethodExitBlock, numBlocks++);
 
-    /* Allocate Registers */
-    dvmCompilerRegAlloc(cUnit);
+    cUnit.entryBlock = entryBlock;
+    cUnit.exitBlock = exitBlock;
 
-    /* Convert MIR to LIR, etc. */
-    dvmCompilerMIR2LIR(cUnit);
+    dvmInsertGrowableList(&cUnit.blockList, (intptr_t) entryBlock);
+    dvmInsertGrowableList(&cUnit.blockList, (intptr_t) exitBlock);
+
+    /* Current block to record parsed instructions */
+    BasicBlock *curBlock = dvmCompilerNewBB(kDalvikByteCode, numBlocks++);
+    curBlock->startOffset = 0;
+    dvmInsertGrowableList(&cUnit.blockList, (intptr_t) curBlock);
+    entryBlock->fallThrough = curBlock;
+    dvmCompilerSetBit(curBlock->predecessors, entryBlock->id);
+
+    /*
+     * Store back the number of blocks since new blocks may be created of
+     * accessing cUnit.
+     */
+    cUnit.numBlocks = numBlocks;
 
-    /* Convert LIR into machine code. */
-    dvmCompilerAssembleLIR(cUnit, info);
+    /* Identify code range in try blocks and set up the empty catch blocks */
+    processTryCatchBlocks(&cUnit);
 
-    if (cUnit->assemblerStatus != kSuccess) {
-        return false;
+    /* Parse all instructions and put them into containing basic blocks */
+    while (codePtr < codeEnd) {
+        MIR *insn = (MIR *) dvmCompilerNew(sizeof(MIR), true);
+        insn->offset = curOffset;
+        int width = parseInsn(codePtr, &insn->dalvikInsn, false);
+        insn->width = width;
+
+        /* Terminate when the data section is seen */
+        if (width == 0)
+            break;
+
+        dvmCompilerAppendMIR(curBlock, insn);
+
+        codePtr += width;
+        int flags = dexGetFlagsFromOpcode(insn->dalvikInsn.opcode);
+
+        if (flags & kInstrCanBranch) {
+            processCanBranch(&cUnit, curBlock, insn, curOffset, width, flags,
+                             codePtr, codeEnd);
+        } else if (flags & kInstrCanReturn) {
+            curBlock->fallThrough = exitBlock;
+            dvmCompilerSetBit(exitBlock->predecessors, curBlock->id);
+            /*
+             * Terminate the current block if there are instructions
+             * afterwards.
+             */
+            if (codePtr < codeEnd) {
+                /*
+                 * Create a fallthrough block for real instructions
+                 * (incl. OP_NOP).
+                 */
+                if (contentIsInsn(codePtr)) {
+                    findBlock(&cUnit, curOffset + width,
+                              /* split */
+                              false,
+                              /* create */
+                              true);
+                }
+            }
+        } else if (flags & kInstrCanThrow) {
+            processCanThrow(&cUnit, curBlock, insn, curOffset, width, flags,
+                            tryBlockAddr, codePtr, codeEnd);
+        } else if (flags & kInstrCanSwitch) {
+            processCanSwitch(&cUnit, curBlock, insn, curOffset, width, flags);
+        }
+        curOffset += width;
+        BasicBlock *nextBlock = findBlock(&cUnit, curOffset,
+                                          /* split */
+                                          false,
+                                          /* create */
+                                          false);
+        if (nextBlock) {
+            /*
+             * The next instruction could be the target of a previously parsed
+             * forward branch so a block is already created. If the current
+             * instruction is not an unconditional branch, connect them through
+             * the fall-through link.
+             */
+            assert(curBlock->fallThrough == NULL ||
+                   curBlock->fallThrough == nextBlock ||
+                   curBlock->fallThrough == exitBlock);
+
+            if ((curBlock->fallThrough == NULL) &&
+                !dexIsGoto(flags) &&
+                !(flags & kInstrCanReturn)) {
+                curBlock->fallThrough = nextBlock;
+                dvmCompilerSetBit(nextBlock->predecessors, curBlock->id);
+            }
+            curBlock = nextBlock;
+        }
     }
 
-    dvmCompilerDumpCompilationUnit(cUnit);
+    /* Adjust this value accordingly once inlining is performed */
+    cUnit.numDalvikRegisters = cUnit.method->registersSize;
+
+    /* Verify if all blocks are connected as claimed */
+    /* FIXME - to be disabled in the future */
+    dvmCompilerDataFlowAnalysisDispatcher(&cUnit, verifyPredInfo,
+                                          kAllNodes,
+                                          false /* isIterative */);
+
+
+    /* Perform SSA transformation for the whole method */
+    dvmCompilerMethodSSATransformation(&cUnit);
 
+    if (cUnit.printMe) dumpCFG(&cUnit, "/data/tombstones/");
+
+    /* Reset the compiler resource pool */
     dvmCompilerArenaReset();
 
-    return info->codeAddress != NULL;
+    return false;
 }
index d9a6eea..2cdba18 100644 (file)
@@ -284,14 +284,16 @@ static void tryInlineVirtualCallsite(CompilationUnit *cUnit,
 
 void dvmCompilerInlineMIR(CompilationUnit *cUnit)
 {
-    int i;
     bool isRange = false;
+    GrowableListIterator iterator;
 
+    dvmGrowableListIteratorInit(&cUnit->blockList, &iterator);
     /*
      * Analyze the basic block containing an invoke to see if it can be inlined
      */
-    for (i = 0; i < cUnit->numBlocks; i++) {
-        BasicBlock *bb = cUnit->blockList[i];
+    while (true) {
+        BasicBlock *bb = (BasicBlock *) dvmGrowableListIteratorNext(&iterator);
+        if (bb == NULL) break;
         if (bb->blockType != kDalvikByteCode)
             continue;
         MIR *lastMIRInsn = bb->lastMIRInsn;
index 2988900..db68c3c 100644 (file)
 #include "CompilerInternals.h"
 
 /* Allocate a new basic block */
-BasicBlock *dvmCompilerNewBB(BBType blockType)
+BasicBlock *dvmCompilerNewBB(BBType blockType, int blockId)
 {
     BasicBlock *bb = (BasicBlock *)dvmCompilerNew(sizeof(BasicBlock), true);
     bb->blockType = blockType;
+    bb->id = blockId;
+    bb->predecessors = dvmCompilerAllocBitVector(blockId > 32 ? blockId : 32,
+                                                 true /* expandable */);
     return bb;
 }
 
index 32d9b09..9ee430d 100644 (file)
  */
 static void handlePhiPlacement(CompilationUnit *cUnit)
 {
-    BasicBlock *entry = cUnit->blockList[0];
-    BasicBlock *loopBody = cUnit->blockList[1];
-    BasicBlock *loopBranch = cUnit->blockList[2];
+    BasicBlock *entry =
+        (BasicBlock *) dvmGrowableListGetElement(&cUnit->blockList, 0);
+    BasicBlock *loopBody =
+        (BasicBlock *) dvmGrowableListGetElement(&cUnit->blockList, 1);
+    BasicBlock *loopBranch =
+        (BasicBlock *) dvmGrowableListGetElement(&cUnit->blockList, 2);
     dvmCopyBitVector(entry->dataFlowInfo->defV,
                      loopBody->dataFlowInfo->liveInV);
 
     BitVector *phiV = dvmCompilerAllocBitVector(cUnit->method->registersSize,
                                                 false);
+    BitVector *phi2V = dvmCompilerAllocBitVector(cUnit->method->registersSize,
+                                                 false);
     dvmIntersectBitVectors(phiV, entry->dataFlowInfo->defV,
                            loopBody->dataFlowInfo->defV);
-    dvmIntersectBitVectors(phiV, entry->dataFlowInfo->defV,
+    dvmIntersectBitVectors(phi2V, entry->dataFlowInfo->defV,
                            loopBranch->dataFlowInfo->defV);
+    dvmUnifyBitVectors(phiV, phiV, phi2V);
 
     /* Insert the PHI MIRs */
     int i;
@@ -66,9 +72,12 @@ static void handlePhiPlacement(CompilationUnit *cUnit)
 
 static void fillPhiNodeContents(CompilationUnit *cUnit)
 {
-    BasicBlock *entry = cUnit->blockList[0];
-    BasicBlock *loopBody = cUnit->blockList[1];
-    BasicBlock *loopBranch = cUnit->blockList[2];
+    BasicBlock *entry =
+        (BasicBlock *) dvmGrowableListGetElement(&cUnit->blockList, 0);
+    BasicBlock *loopBody =
+        (BasicBlock *) dvmGrowableListGetElement(&cUnit->blockList, 1);
+    BasicBlock *loopBranch =
+        (BasicBlock *) dvmGrowableListGetElement(&cUnit->blockList, 2);
     MIR *mir;
 
     for (mir = loopBody->firstMIRInsn; mir; mir = mir->next) {
@@ -165,7 +174,8 @@ static void dumpHoistedChecks(CompilationUnit *cUnit)
 static bool isLoopOptimizable(CompilationUnit *cUnit)
 {
     unsigned int i;
-    BasicBlock *loopBranch = cUnit->blockList[2];
+    BasicBlock *loopBranch =
+        (BasicBlock *) dvmGrowableListGetElement(&cUnit->blockList, 2);
     LoopAnalysis *loopAnalysis = cUnit->loopAnalysis;
 
     if (loopAnalysis->numBasicIV != 1) return false;
@@ -290,7 +300,7 @@ static void updateRangeCheckInfo(CompilationUnit *cUnit, int arrayReg,
                 arrayAccessInfo->maxC = (ivInfo->c > 0) ? ivInfo->c : 0;
                 arrayAccessInfo->minC = (ivInfo->c < 0) ? ivInfo->c : 0;
                 dvmInsertGrowableList(loopAnalysis->arrayAccessInfo,
-                                      arrayAccessInfo);
+                                      (intptr_t) arrayAccessInfo);
             }
             break;
         }
@@ -300,7 +310,8 @@ static void updateRangeCheckInfo(CompilationUnit *cUnit, int arrayReg,
 /* Returns true if the loop body cannot throw any exceptions */
 static bool doLoopBodyCodeMotion(CompilationUnit *cUnit)
 {
-    BasicBlock *loopBody = cUnit->blockList[1];
+    BasicBlock *loopBody =
+        (BasicBlock *) dvmGrowableListGetElement(&cUnit->blockList, 1);
     MIR *mir;
     bool loopBodyCanThrow = false;
 
@@ -387,7 +398,8 @@ static bool doLoopBodyCodeMotion(CompilationUnit *cUnit)
 static void genHoistedChecks(CompilationUnit *cUnit)
 {
     unsigned int i;
-    BasicBlock *entry = cUnit->blockList[0];
+    BasicBlock *entry =
+        (BasicBlock *) dvmGrowableListGetElement(&cUnit->blockList, 0);
     LoopAnalysis *loopAnalysis = cUnit->loopAnalysis;
     int globalMaxC = 0;
     int globalMinC = 0;
@@ -477,21 +489,28 @@ bool dvmCompilerLoopOpt(CompilationUnit *cUnit)
     LoopAnalysis *loopAnalysis =
         (LoopAnalysis *)dvmCompilerNew(sizeof(LoopAnalysis), true);
 
-    assert(cUnit->blockList[0]->blockType == kTraceEntryBlock);
-    assert(cUnit->blockList[2]->blockType == kDalvikByteCode);
-    assert(cUnit->blockList[3]->blockType == kTraceExitBlock);
+    assert(((BasicBlock *) dvmGrowableListGetElement(&cUnit->blockList, 0))
+                               ->blockType == kTraceEntryBlock);
+    assert(((BasicBlock *) dvmGrowableListGetElement(&cUnit->blockList, 2))
+                               ->blockType == kDalvikByteCode);
+    assert(((BasicBlock *) dvmGrowableListGetElement(&cUnit->blockList, 3))
+                               ->blockType == kTraceExitBlock);
 
     cUnit->loopAnalysis = loopAnalysis;
     /*
      * Find live-in variables to the loop body so that we can fake their
      * definitions in the entry block.
      */
-    dvmCompilerDataFlowAnalysisDispatcher(cUnit, dvmCompilerFindLiveIn);
+    dvmCompilerDataFlowAnalysisDispatcher(cUnit, dvmCompilerFindLocalLiveIn,
+                                          kAllNodes,
+                                          false /* isIterative */);
 
     /* Insert phi nodes to the loop body */
     handlePhiPlacement(cUnit);
 
-    dvmCompilerDataFlowAnalysisDispatcher(cUnit, dvmCompilerDoSSAConversion);
+    dvmCompilerDataFlowAnalysisDispatcher(cUnit, dvmCompilerDoSSAConversion,
+                                          kAllNodes,
+                                          false /* isIterative */);
     fillPhiNodeContents(cUnit);
 
     /* Constant propagation */
@@ -500,7 +519,9 @@ bool dvmCompilerLoopOpt(CompilationUnit *cUnit)
         (int *)dvmCompilerNew(sizeof(int) * cUnit->numSSARegs,
                               true);
     dvmCompilerDataFlowAnalysisDispatcher(cUnit,
-                                          dvmCompilerDoConstantPropagation);
+                                          dvmCompilerDoConstantPropagation,
+                                          kAllNodes,
+                                          false /* isIterative */);
     DEBUG_LOOP(dumpConstants(cUnit);)
 
     /* Find induction variables - basic and dependent */
@@ -509,7 +530,9 @@ bool dvmCompilerLoopOpt(CompilationUnit *cUnit)
     dvmInitGrowableList(loopAnalysis->ivList, 4);
     loopAnalysis->isIndVarV = dvmAllocBitVector(cUnit->numSSARegs, false);
     dvmCompilerDataFlowAnalysisDispatcher(cUnit,
-                                          dvmCompilerFindInductionVariables);
+                                          dvmCompilerFindInductionVariables,
+                                          kAllNodes,
+                                          false /* isIterative */);
     DEBUG_LOOP(dumpIVList(cUnit);)
 
     /* If the loop turns out to be non-optimizable, return early */
diff --git a/vm/compiler/MethodSSATransformation.c b/vm/compiler/MethodSSATransformation.c
new file mode 100644 (file)
index 0000000..fc56891
--- /dev/null
@@ -0,0 +1,559 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "Dalvik.h"
+#include "Dataflow.h"
+#include "Loop.h"
+#include "libdex/DexOpcodes.h"
+
+/* Enter the node to the dfsOrder list then visit its successors */
+static void recordDFSPreOrder(CompilationUnit *cUnit, BasicBlock *block)
+{
+
+    if (block->visited) return;
+    block->visited = true;
+
+    /* Enqueue the block id */
+    dvmInsertGrowableList(&cUnit->dfsOrder, block->id);
+
+    if (block->taken) recordDFSPreOrder(cUnit, block->taken);
+    if (block->fallThrough) recordDFSPreOrder(cUnit, block->fallThrough);
+    if (block->successorBlockList.blockListType != kNotUsed) {
+        GrowableListIterator iterator;
+        dvmGrowableListIteratorInit(&block->successorBlockList.blocks,
+                                    &iterator);
+        while (true) {
+            BasicBlock *succBB =
+                (BasicBlock *) dvmGrowableListIteratorNext(&iterator);
+            if (succBB == NULL) break;
+            recordDFSPreOrder(cUnit, succBB);
+        }
+    }
+    return;
+}
+
+/* Sort the blocks by the Depth-First-Search pre-order */
+static void computeDFSOrder(CompilationUnit *cUnit)
+{
+    /* Initialize the DFS order list */
+    dvmInitGrowableList(&cUnit->dfsOrder, cUnit->numBlocks);
+
+
+    dvmCompilerDataFlowAnalysisDispatcher(cUnit, dvmCompilerClearVisitedFlag,
+                                          kAllNodes,
+                                          false /* isIterative */);
+
+    recordDFSPreOrder(cUnit, cUnit->entryBlock);
+    cUnit->numReachableBlocks = cUnit->dfsOrder.numUsed;
+}
+
+/*
+ * Mark block bit on the per-Dalvik register vector to denote that Dalvik
+ * register idx is defined in BasicBlock bb.
+ */
+static bool fillDefBlockMatrix(CompilationUnit *cUnit, BasicBlock *bb)
+{
+    if (bb->dataFlowInfo == NULL) return false;
+
+    BitVectorIterator iterator;
+
+    dvmBitVectorIteratorInit(bb->dataFlowInfo->defV, &iterator);
+    while (true) {
+        int idx = dvmBitVectorIteratorNext(&iterator);
+        if (idx == -1) break;
+        /* Block bb defines register idx */
+        dvmCompilerSetBit(cUnit->defBlockMatrix[idx], bb->id);
+    }
+    return true;
+}
+
+static void computeDefBlockMatrix(CompilationUnit *cUnit)
+{
+    int numRegisters = cUnit->numDalvikRegisters;
+    /* Allocate numDalvikRegisters bit vector pointers */
+    cUnit->defBlockMatrix = (BitVector **)
+        dvmCompilerNew(sizeof(BitVector *) * numRegisters, true);
+    int i;
+
+    /* Initialize numRegister vectors with numBlocks bits each */
+    for (i = 0; i < numRegisters; i++) {
+        cUnit->defBlockMatrix[i] = dvmCompilerAllocBitVector(cUnit->numBlocks,
+                                                             false);
+    }
+    dvmCompilerDataFlowAnalysisDispatcher(cUnit, dvmCompilerFindLocalLiveIn,
+                                          kAllNodes,
+                                          false /* isIterative */);
+    dvmCompilerDataFlowAnalysisDispatcher(cUnit, fillDefBlockMatrix,
+                                          kAllNodes,
+                                          false /* isIterative */);
+
+    /*
+     * Also set the incoming parameters as defs in the entry block.
+     * Only need to handle the parameters for the outer method.
+     */
+    int inReg = cUnit->method->registersSize - cUnit->method->insSize;
+    for (; inReg < cUnit->method->registersSize; inReg++) {
+        dvmCompilerSetBit(cUnit->defBlockMatrix[inReg],
+                          cUnit->entryBlock->id);
+    }
+}
+
+/* Compute the post-order traversal of the CFG */
+static void computeDomPostOrderTraversal(CompilationUnit *cUnit, BasicBlock *bb)
+{
+    BitVectorIterator bvIterator;
+    dvmBitVectorIteratorInit(bb->iDominated, &bvIterator);
+    GrowableList *blockList = &cUnit->blockList;
+
+    /* Iterate through the dominated blocks first */
+    while (true) {
+        int bbIdx = dvmBitVectorIteratorNext(&bvIterator);
+        if (bbIdx == -1) break;
+        BasicBlock *dominatedBB =
+            (BasicBlock *) dvmGrowableListGetElement(blockList, bbIdx);
+        computeDomPostOrderTraversal(cUnit, dominatedBB);
+    }
+
+    /* Enter the current block id */
+    dvmInsertGrowableList(&cUnit->domPostOrderTraversal, bb->id);
+
+    /* hacky loop detection */
+    if (bb->taken && dvmIsBitSet(bb->dominators, bb->taken->id)) {
+        cUnit->hasLoop = true;
+    }
+}
+
+/* Worker function to compute the dominance frontier */
+static bool computeDominanceFrontier(CompilationUnit *cUnit, BasicBlock *bb)
+{
+    GrowableList *blockList = &cUnit->blockList;
+
+    /* Calculate DF_local */
+    if (bb->taken && !dvmIsBitSet(bb->taken->dominators, bb->id)) {
+        dvmSetBit(bb->domFrontier, bb->taken->id);
+    }
+    if (bb->fallThrough &&
+        !dvmIsBitSet(bb->fallThrough->dominators, bb->id)) {
+        dvmSetBit(bb->domFrontier, bb->fallThrough->id);
+    }
+    if (bb->successorBlockList.blockListType != kNotUsed) {
+        GrowableListIterator iterator;
+        dvmGrowableListIteratorInit(&bb->successorBlockList.blocks,
+                                    &iterator);
+        while (true) {
+            BasicBlock *succBB =
+                (BasicBlock *) dvmGrowableListIteratorNext(&iterator);
+            if (succBB == NULL) break;
+            if (!dvmIsBitSet(succBB->dominators, bb->id)) {
+                dvmSetBit(bb->domFrontier, succBB->id);
+            }
+        }
+    }
+
+    /* Calculate DF_up */
+    BitVectorIterator bvIterator;
+    dvmBitVectorIteratorInit(bb->iDominated, &bvIterator);
+    while (true) {
+        int dominatedIdx = dvmBitVectorIteratorNext(&bvIterator);
+        if (dominatedIdx == -1) break;
+        BasicBlock *dominatedBB = (BasicBlock *)
+            dvmGrowableListGetElement(blockList, dominatedIdx);
+        BitVectorIterator dfIterator;
+        dvmBitVectorIteratorInit(dominatedBB->domFrontier, &dfIterator);
+        while (true) {
+            int dfUpIdx = dvmBitVectorIteratorNext(&dfIterator);
+            if (dfUpIdx == -1) break;
+            BasicBlock *dfUpBlock = (BasicBlock *)
+                dvmGrowableListGetElement(blockList, dfUpIdx);
+            if (!dvmIsBitSet(dfUpBlock->dominators, bb->id)) {
+                dvmSetBit(bb->domFrontier, dfUpBlock->id);
+            }
+        }
+    }
+    if (cUnit->printMe) {
+        char blockName[BLOCK_NAME_LEN];
+        dvmGetBlockName(bb, blockName);
+        dvmDumpBlockBitVector(blockList, blockName, bb->domFrontier,
+                              cUnit->numBlocks);
+    }
+
+    return true;
+}
+
+/* Worker function for initializing domination-related data structures */
+static bool initializeDominationInfo(CompilationUnit *cUnit, BasicBlock *bb)
+{
+    int numTotalBlocks = cUnit->blockList.numUsed;
+
+    bb->dominators = dvmCompilerAllocBitVector(numTotalBlocks,
+                                               false /* expandable */);
+    bb->iDominated = dvmCompilerAllocBitVector(numTotalBlocks,
+                                               false /* expandable */);
+    bb->domFrontier = dvmCompilerAllocBitVector(numTotalBlocks,
+                                               false /* expandable */);
+    /* Set all bits in the dominator vector */
+    dvmSetInitialBits(bb->dominators, numTotalBlocks);
+
+    return true;
+}
+
+/* Worker function to compute each block's dominators */
+static bool computeBlockDominators(CompilationUnit *cUnit, BasicBlock *bb)
+{
+    GrowableList *blockList = &cUnit->blockList;
+    int numTotalBlocks = blockList->numUsed;
+    BitVector *tempBlockV = cUnit->tempBlockV;
+    BitVectorIterator bvIterator;
+
+    /*
+     * The dominator of the entry block has been preset to itself and we need
+     * to skip the calculation here.
+     */
+    if (bb == cUnit->entryBlock) return false;
+
+    dvmSetInitialBits(tempBlockV, numTotalBlocks);
+
+    /* Iterate through the predecessors */
+    dvmBitVectorIteratorInit(bb->predecessors, &bvIterator);
+    while (true) {
+        int predIdx = dvmBitVectorIteratorNext(&bvIterator);
+        if (predIdx == -1) break;
+        BasicBlock *predBB = (BasicBlock *) dvmGrowableListGetElement(
+                                 blockList, predIdx);
+        /* tempBlockV = tempBlockV ^ dominators */
+        dvmIntersectBitVectors(tempBlockV, tempBlockV, predBB->dominators);
+    }
+    dvmSetBit(tempBlockV, bb->id);
+    if (dvmCompareBitVectors(tempBlockV, bb->dominators)) {
+        dvmCopyBitVector(bb->dominators, tempBlockV);
+        return true;
+    }
+    return false;
+}
+
+/* Worker function to compute the idom */
+static bool computeImmediateDominator(CompilationUnit *cUnit, BasicBlock *bb)
+{
+    GrowableList *blockList = &cUnit->blockList;
+    BitVector *tempBlockV = cUnit->tempBlockV;
+    BitVectorIterator bvIterator;
+    BasicBlock *iDom;
+
+    if (bb == cUnit->entryBlock) return false;
+
+    dvmCopyBitVector(tempBlockV, bb->dominators);
+    dvmClearBit(tempBlockV, bb->id);
+    dvmBitVectorIteratorInit(tempBlockV, &bvIterator);
+
+    /* Should not see any dead block */
+    assert(dvmCountSetBits(tempBlockV) != 0);
+    if (dvmCountSetBits(tempBlockV) == 1) {
+        iDom = (BasicBlock *) dvmGrowableListGetElement(
+                       blockList, dvmBitVectorIteratorNext(&bvIterator));
+        bb->iDom = iDom;
+    } else {
+        int iDomIdx = dvmBitVectorIteratorNext(&bvIterator);
+        assert(iDomIdx != -1);
+        while (true) {
+            int nextDom = dvmBitVectorIteratorNext(&bvIterator);
+            if (nextDom == -1) break;
+            BasicBlock *nextDomBB = (BasicBlock *)
+                dvmGrowableListGetElement(blockList, nextDom);
+            /* iDom dominates nextDom - set new iDom */
+            if (dvmIsBitSet(nextDomBB->dominators, iDomIdx)) {
+                iDomIdx = nextDom;
+            }
+
+        }
+        iDom = (BasicBlock *) dvmGrowableListGetElement(blockList, iDomIdx);
+        /* Set the immediate dominator block for bb */
+        bb->iDom = iDom;
+    }
+    /* Add bb to the iDominated set of the immediate dominator block */
+    dvmCompilerSetBit(iDom->iDominated, bb->id);
+    return true;
+}
+
+/* Compute dominators, immediate dominator, and dominance fronter */
+static void computeDominators(CompilationUnit *cUnit)
+{
+    int numReachableBlocks = cUnit->numReachableBlocks;
+    int numTotalBlocks = cUnit->blockList.numUsed;
+
+    /* Initialize domination-related data structures */
+    dvmCompilerDataFlowAnalysisDispatcher(cUnit, initializeDominationInfo,
+                                          kReachableNodes,
+                                          false /* isIterative */);
+
+    /* Set the dominator for the root node */
+    dvmClearAllBits(cUnit->entryBlock->dominators);
+    dvmSetBit(cUnit->entryBlock->dominators, cUnit->entryBlock->id);
+
+    cUnit->tempBlockV = dvmCompilerAllocBitVector(numTotalBlocks,
+                                              false /* expandable */);
+    dvmCompilerDataFlowAnalysisDispatcher(cUnit, computeBlockDominators,
+                                          kPreOrderDFSTraversal,
+                                          true /* isIterative */);
+
+    cUnit->entryBlock->iDom = NULL;
+    dvmCompilerDataFlowAnalysisDispatcher(cUnit, computeImmediateDominator,
+                                          kReachableNodes,
+                                          false /* isIterative */);
+
+    /*
+     * Now go ahead and compute the post order traversal based on the
+     * iDominated sets.
+     */
+    dvmInitGrowableList(&cUnit->domPostOrderTraversal, numReachableBlocks);
+    computeDomPostOrderTraversal(cUnit, cUnit->entryBlock);
+    assert(cUnit->domPostOrderTraversal.numUsed ==
+           (unsigned) cUnit->numReachableBlocks);
+
+    /* Now compute the dominance frontier for each block */
+    dvmCompilerDataFlowAnalysisDispatcher(cUnit, computeDominanceFrontier,
+                                          kPostOrderDOMTraversal,
+                                          false /* isIterative */);
+}
+
+/*
+ * Perform dest U= src1 ^ ~src2
+ * This is probably not general enough to be placed in BitVector.[ch].
+ */
+static void computeSuccLiveIn(BitVector *dest,
+                              const BitVector *src1,
+                              const BitVector *src2)
+{
+    if (dest->storageSize != src1->storageSize ||
+        dest->storageSize != src2->storageSize ||
+        dest->expandable != src1->expandable ||
+        dest->expandable != src2->expandable) {
+        LOGE("Incompatible set properties");
+        dvmAbort();
+    }
+
+    int i;
+    for (i = 0; i < dest->storageSize; i++) {
+        dest->storage[i] |= src1->storage[i] & ~src2->storage[i];
+    }
+}
+
+/*
+ * Iterate through all successor blocks and propagate up the live-in sets.
+ * The calculated result is used for phi-node pruning - where we only need to
+ * insert a phi node if the variable is live-in to the block.
+ */
+static bool computeBlockLiveIns(CompilationUnit *cUnit, BasicBlock *bb)
+{
+    BitVector *tempDalvikRegisterV = cUnit->tempDalvikRegisterV;
+
+    if (bb->dataFlowInfo == NULL) return false;
+    dvmCopyBitVector(tempDalvikRegisterV, bb->dataFlowInfo->liveInV);
+    if (bb->taken && bb->taken->dataFlowInfo)
+        computeSuccLiveIn(tempDalvikRegisterV, bb->taken->dataFlowInfo->liveInV,
+                          bb->dataFlowInfo->defV);
+    if (bb->fallThrough && bb->fallThrough->dataFlowInfo)
+        computeSuccLiveIn(tempDalvikRegisterV,
+                          bb->fallThrough->dataFlowInfo->liveInV,
+                          bb->dataFlowInfo->defV);
+    if (bb->successorBlockList.blockListType != kNotUsed) {
+        GrowableListIterator iterator;
+        dvmGrowableListIteratorInit(&bb->successorBlockList.blocks,
+                                    &iterator);
+        while (true) {
+            BasicBlock *succBB =
+                (BasicBlock *) dvmGrowableListIteratorNext(&iterator);
+            if (succBB == NULL) break;
+            if (succBB->dataFlowInfo) {
+                computeSuccLiveIn(tempDalvikRegisterV,
+                                  succBB->dataFlowInfo->liveInV,
+                                  bb->dataFlowInfo->defV);
+            }
+        }
+    }
+    if (dvmCompareBitVectors(tempDalvikRegisterV, bb->dataFlowInfo->liveInV)) {
+        dvmCopyBitVector(bb->dataFlowInfo->liveInV, tempDalvikRegisterV);
+        return true;
+    }
+    return false;
+}
+
+/* Insert phi nodes to for each variable to the dominance frontiers */
+static void insertPhiNodes(CompilationUnit *cUnit)
+{
+    int dalvikReg;
+    const GrowableList *blockList = &cUnit->blockList;
+    BitVector *phiBlocks =
+        dvmCompilerAllocBitVector(cUnit->numDalvikRegisters, false);
+    BitVector *tmpBlocks =
+        dvmCompilerAllocBitVector(cUnit->numDalvikRegisters, false);
+    BitVector *inputBlocks =
+        dvmCompilerAllocBitVector(cUnit->numDalvikRegisters, false);
+
+    cUnit->tempDalvikRegisterV =
+        dvmCompilerAllocBitVector(cUnit->numDalvikRegisters, false);
+
+    dvmCompilerDataFlowAnalysisDispatcher(cUnit, computeBlockLiveIns,
+                                          kPostOrderDFSTraversal,
+                                          true /* isIterative */);
+
+    /* Iterate through each Dalvik register */
+    for (dalvikReg = 0; dalvikReg < cUnit->numDalvikRegisters; dalvikReg++) {
+        bool change;
+        BitVectorIterator iterator;
+
+        dvmCopyBitVector(inputBlocks, cUnit->defBlockMatrix[dalvikReg]);
+        dvmClearAllBits(phiBlocks);
+        /* Calculate the phi blocks for each Dalvik register */
+        do {
+            change = false;
+            dvmClearAllBits(tmpBlocks);
+            dvmBitVectorIteratorInit(inputBlocks, &iterator);
+            while (true) {
+                int idx = dvmBitVectorIteratorNext(&iterator);
+                if (idx == -1) break;
+                BasicBlock *defBB =
+                    (BasicBlock *) dvmGrowableListGetElement(blockList, idx);
+                /* Merge the dominance frontier to tmpBlocks */
+                dvmUnifyBitVectors(tmpBlocks, tmpBlocks, defBB->domFrontier);
+            }
+            if (dvmCompareBitVectors(phiBlocks, tmpBlocks)) {
+                change = true;
+                dvmCopyBitVector(phiBlocks, tmpBlocks);
+
+                /*
+                 * Iterate through the original blocks plus the new ones in
+                 * the dominance frontier.
+                 */
+                dvmCopyBitVector(inputBlocks, phiBlocks);
+                dvmUnifyBitVectors(inputBlocks, inputBlocks,
+                                   cUnit->defBlockMatrix[dalvikReg]);
+            }
+        } while (change);
+
+        /*
+         * Insert a phi node for dalvikReg in the phiBlocks if the Dalvik
+         * register is in the live-in set.
+         */
+        dvmBitVectorIteratorInit(phiBlocks, &iterator);
+        while (true) {
+            int idx = dvmBitVectorIteratorNext(&iterator);
+            if (idx == -1) break;
+            BasicBlock *phiBB =
+                (BasicBlock *) dvmGrowableListGetElement(blockList, idx);
+            /* Variable will be clobbered before being used - no need for phi */
+            if (!dvmIsBitSet(phiBB->dataFlowInfo->liveInV, dalvikReg)) continue;
+            MIR *phi = (MIR *) dvmCompilerNew(sizeof(MIR), true);
+            phi->dalvikInsn.opcode = kMirOpPhi;
+            phi->dalvikInsn.vA = dalvikReg;
+            phi->offset = phiBB->startOffset;
+            dvmCompilerPrependMIR(phiBB, phi);
+        }
+    }
+}
+
+/*
+ * Worker function to insert phi-operands with latest SSA names from
+ * predecessor blocks
+ */
+static bool insertPhiNodeOperands(CompilationUnit *cUnit, BasicBlock *bb)
+{
+    BitVector *ssaRegV = cUnit->tempSSARegisterV;
+    BitVectorIterator bvIterator;
+    GrowableList *blockList = &cUnit->blockList;
+    MIR *mir;
+
+    /* Phi nodes are at the beginning of each block */
+    for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
+        if (mir->dalvikInsn.opcode != kMirOpPhi) return true;
+        int ssaReg = mir->ssaRep->defs[0];
+        int encodedDalvikValue =
+            (int) dvmGrowableListGetElement(cUnit->ssaToDalvikMap, ssaReg);
+        int dalvikReg = DECODE_REG(encodedDalvikValue);
+
+        dvmClearAllBits(ssaRegV);
+
+        /* Iterate through the predecessors */
+        dvmBitVectorIteratorInit(bb->predecessors, &bvIterator);
+        while (true) {
+            int predIdx = dvmBitVectorIteratorNext(&bvIterator);
+            if (predIdx == -1) break;
+            BasicBlock *predBB = (BasicBlock *) dvmGrowableListGetElement(
+                                     blockList, predIdx);
+            int encodedSSAValue =
+                predBB->dataFlowInfo->dalvikToSSAMap[dalvikReg];
+            int ssaReg = DECODE_REG(encodedSSAValue);
+            dvmSetBit(ssaRegV, ssaReg);
+        }
+
+        /* Count the number of SSA registers for a Dalvik register */
+        int numUses = dvmCountSetBits(ssaRegV);
+        mir->ssaRep->numUses = numUses;
+        mir->ssaRep->uses =
+            (int *) dvmCompilerNew(sizeof(int) * numUses, false);
+        mir->ssaRep->fpUse =
+            (bool *) dvmCompilerNew(sizeof(bool) * numUses, false);
+
+        BitVectorIterator phiIterator;
+
+        dvmBitVectorIteratorInit(ssaRegV, &phiIterator);
+        int *usePtr = mir->ssaRep->uses;
+
+        /* Set the uses array for the phi node */
+        while (true) {
+            int ssaRegIdx = dvmBitVectorIteratorNext(&phiIterator);
+            if (ssaRegIdx == -1) break;
+            *usePtr++ = ssaRegIdx;
+        }
+    }
+
+    return true;
+}
+
+/* Perform SSA transformation for the whole method */
+void dvmCompilerMethodSSATransformation(CompilationUnit *cUnit)
+{
+    /* Compute the DFS order */
+    computeDFSOrder(cUnit);
+
+    /* Compute the dominator info */
+    computeDominators(cUnit);
+
+    /* Allocate data structures in preparation for SSA conversion */
+    dvmInitializeSSAConversion(cUnit);
+
+    /* Find out the "Dalvik reg def x block" relation */
+    computeDefBlockMatrix(cUnit);
+
+    /* Insert phi nodes to dominance frontiers for all variables */
+    insertPhiNodes(cUnit);
+
+    /* Rename register names by local defs and phi nodes */
+    dvmCompilerDataFlowAnalysisDispatcher(cUnit, dvmCompilerDoSSAConversion,
+                                          kPreOrderDFSTraversal,
+                                          false /* isIterative */);
+
+    /*
+     * Shared temp bit vector used by each block to count the number of defs
+     * from all the predecessor blocks.
+     */
+    cUnit->tempSSARegisterV = dvmCompilerAllocBitVector(cUnit->numSSARegs,
+                                                        false);
+
+    /* Insert phi-operands with latest SSA names from predecessor blocks */
+    dvmCompilerDataFlowAnalysisDispatcher(cUnit, insertPhiNodeOperands,
+                                          kReachableNodes,
+                                          false /* isIterative */);
+}
index 0dd67b7..130ff3c 100644 (file)
@@ -25,35 +25,6 @@ typedef struct LiveRange {
     int last;
 } LiveRange;
 
-static int computeLiveRange(LiveRange *list, BasicBlock *bb, int seqNum)
-{
-    MIR *mir;
-    int i;
-
-    if (bb->blockType != kDalvikByteCode &&
-        bb->blockType != kTraceEntryBlock)
-        return seqNum;
-
-    for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
-        SSARepresentation *ssaRep = mir->ssaRep;
-        mir->seqNum = seqNum;
-        if (ssaRep) {
-            for (i=0; i< ssaRep->numUses; i++) {
-                int reg = ssaRep->uses[i];
-                list[reg].first = MIN(list[reg].first, seqNum);
-                list[reg].active = true;
-            }
-            for (i=0; i< ssaRep->numDefs; i++) {
-                int reg = ssaRep->defs[i];
-                list[reg].last = MAX(list[reg].last, seqNum + 1);
-                list[reg].active = true;
-            }
-            seqNum += 2;
-        }
-    }
-    return seqNum;
-}
-
 /*
  * Quick & dirty - make FP usage sticky.  This is strictly a hint - local
  * code generation will handle misses.  It might be worthwhile to collaborate
@@ -121,7 +92,6 @@ static const RegLocation freshLoc = {kLocDalvikFrame, 0, 0, INVALID_REG,
 void dvmCompilerRegAlloc(CompilationUnit *cUnit)
 {
     int i;
-    int seqNum = 0;
     LiveRange *ranges;
     RegLocation *loc;
 
@@ -133,9 +103,14 @@ void dvmCompilerRegAlloc(CompilationUnit *cUnit)
     }
     cUnit->regLocation = loc;
 
+    GrowableListIterator iterator;
+
+    dvmGrowableListIteratorInit(&cUnit->blockList, &iterator);
     /* Do type inference pass */
-    for (i=0; i < cUnit->numBlocks; i++) {
-        inferTypes(cUnit, cUnit->blockList[i]);
+    while (true) {
+        BasicBlock *bb = (BasicBlock *) dvmGrowableListIteratorNext(&iterator);
+        if (bb == NULL) break;
+        inferTypes(cUnit, bb);
     }
 
     if (simpleTrace(cUnit)) {
@@ -153,7 +128,6 @@ void dvmCompilerRegAlloc(CompilationUnit *cUnit)
         ranges = (LiveRange *)dvmCompilerNew(cUnit->numSSARegs * sizeof(*ranges), true);
         for (i=0; i < cUnit->numSSARegs; i++)
             ranges[i].active = false;
-        seqNum = computeLiveRange(ranges, cUnit->blockList[i], seqNum);
         //TODO: phi squash & linear scan promotion
     }
 }
index 4b942ef..fe25833 100644 (file)
@@ -82,7 +82,8 @@ retry:
             LOGI("Total arena pages for JIT: %d", numArenaBlocks);
         goto retry;
     }
-    return NULL;
+    /* Should not reach here */
+    dvmAbort();
 }
 
 /* Reclaim all the arena blocks allocated so far */
@@ -101,8 +102,8 @@ void dvmInitGrowableList(GrowableList *gList, size_t initLength)
 {
     gList->numAllocated = initLength;
     gList->numUsed = 0;
-    gList->elemList = (void **) dvmCompilerNew(sizeof(void *) * initLength,
-                                               true);
+    gList->elemList = (intptr_t *) dvmCompilerNew(sizeof(intptr_t) * initLength,
+                                                  true);
 }
 
 /* Expand the capacity of a growable list */
@@ -114,14 +115,15 @@ static void expandGrowableList(GrowableList *gList)
     } else {
         newLength += 128;
     }
-    void *newArray = dvmCompilerNew(sizeof(void *) * newLength, true);
-    memcpy(newArray, gList->elemList, sizeof(void *) * gList->numAllocated);
+    intptr_t *newArray =
+        (intptr_t *) dvmCompilerNew(sizeof(intptr_t) * newLength, true);
+    memcpy(newArray, gList->elemList, sizeof(intptr_t) * gList->numAllocated);
     gList->numAllocated = newLength;
-    gList->elemList = (void **)newArray;
+    gList->elemList = newArray;
 }
 
 /* Insert a new element into the growable list */
-void dvmInsertGrowableList(GrowableList *gList, void *elem)
+void dvmInsertGrowableList(GrowableList *gList, intptr_t elem)
 {
     assert(gList->numAllocated != 0);
     if (gList->numUsed == gList->numAllocated) {
@@ -130,10 +132,30 @@ void dvmInsertGrowableList(GrowableList *gList, void *elem)
     gList->elemList[gList->numUsed++] = elem;
 }
 
+void dvmGrowableListIteratorInit(GrowableList *gList,
+                                 GrowableListIterator *iterator)
+{
+    iterator->list = gList;
+    iterator->idx = 0;
+    iterator->size = gList->numUsed;
+}
+
+intptr_t dvmGrowableListIteratorNext(GrowableListIterator *iterator)
+{
+    assert(iterator->size == iterator->list->numUsed);
+    if (iterator->idx == iterator->size) return 0;
+    return iterator->list->elemList[iterator->idx++];
+}
+
+intptr_t dvmGrowableListGetElement(const GrowableList *gList, size_t idx)
+{
+    assert(idx < gList->numUsed);
+    return gList->elemList[idx];
+}
+
 /* Debug Utility - dump a compilation unit */
 void dvmCompilerDumpCompilationUnit(CompilationUnit *cUnit)
 {
-    int i;
     BasicBlock *bb;
     char *blockTypeNames[] = {
         "Normal Chaining Cell",
@@ -156,9 +178,13 @@ void dvmCompilerDumpCompilationUnit(CompilationUnit *cUnit)
          cUnit->method->name);
     LOGD("%d insns", dvmGetMethodInsnsSize(cUnit->method));
     LOGD("%d blocks in total", cUnit->numBlocks);
+    GrowableListIterator iterator;
+
+    dvmGrowableListIteratorInit(&cUnit->blockList, &iterator);
 
-    for (i = 0; i < cUnit->numBlocks; i++) {
-        bb = cUnit->blockList[i];
+    while (true) {
+        bb = (BasicBlock *) dvmGrowableListIteratorNext(&iterator);
+        if (bb == NULL) break;
         LOGD("Block %d (%s) (insn %04x - %04x%s)\n",
              bb->id,
              blockTypeNames[bb->blockType],
@@ -275,7 +301,7 @@ bool dvmCompilerSetBit(BitVector *pBits, int num)
     assert(num >= 0);
     if (num >= pBits->storageSize * (int)sizeof(u4) * 8) {
         if (!pBits->expandable)
-            return false;
+            dvmAbort();
 
         /* Round up to word boundaries for "num+1" bits */
         int newSize = (num + 1 + 31) >> 5;
@@ -292,6 +318,36 @@ bool dvmCompilerSetBit(BitVector *pBits, int num)
     return true;
 }
 
+/*
+ * Mark the specified bit as "unset".
+ *
+ * Returns "false" if the bit is outside the range of the vector and we're
+ * not allowed to expand.
+ *
+ * NOTE: this is the sister implementation of dvmClearBit. In this version
+ * memory is allocated from the compiler arena.
+ */
+bool dvmCompilerClearBit(BitVector *pBits, int num)
+{
+    assert(num >= 0);
+    if (num >= pBits->storageSize * (int)sizeof(u4) * 8) {
+        LOGE("Trying to clear a bit that is not set in the vector yet!");
+        dvmAbort();
+    }
+
+    pBits->storage[num >> 5] &= ~(1 << (num & 0x1f));
+    return true;
+}
+
+/*
+ * If set is true, mark all bits as 1. Otherwise mark all bits as 0.
+ */
+void dvmCompilerMarkAllBits(BitVector *pBits, bool set)
+{
+    int value = set ? -1 : 0;
+    memset(pBits->storage, value, pBits->storageSize * (int)sizeof(u4));
+}
+
 void dvmDebugBitVector(char *msg, const BitVector *bv, int length)
 {
     int i;
@@ -315,3 +371,41 @@ void dvmCompilerAbort(CompilationUnit *cUnit)
      */
     longjmp(*cUnit->bailPtr, 1);
 }
+
+void dvmDumpBlockBitVector(const GrowableList *blocks, char *msg,
+                           const BitVector *bv, int length)
+{
+    int i;
+
+    LOGE("%s", msg);
+    for (i = 0; i < length; i++) {
+        if (dvmIsBitSet(bv, i)) {
+            BasicBlock *bb =
+                (BasicBlock *) dvmGrowableListGetElement(blocks, i);
+            char blockName[BLOCK_NAME_LEN];
+            dvmGetBlockName(bb, blockName);
+            LOGE("Bit %d / %s is set", i, blockName);
+        }
+    }
+}
+
+void dvmGetBlockName(BasicBlock *bb, char *name)
+{
+    switch (bb->blockType) {
+        case kMethodEntryBlock:
+            snprintf(name, BLOCK_NAME_LEN, "entry");
+            break;
+        case kMethodExitBlock:
+            snprintf(name, BLOCK_NAME_LEN, "exit");
+            break;
+        case kDalvikByteCode:
+            snprintf(name, BLOCK_NAME_LEN, "block%04x", bb->startOffset);
+            break;
+        case kExceptionHandling:
+            snprintf(name, BLOCK_NAME_LEN, "exception%04x", bb->startOffset);
+            break;
+        default:
+            snprintf(name, BLOCK_NAME_LEN, "??");
+            break;
+    }
+}
index 6558f67..c29efa6 100644 (file)
@@ -376,7 +376,8 @@ static ArmLIR *genCheckCommon(CompilationUnit *cUnit, int dOffset,
         pcrLabel->operands[0] = dPC;
         pcrLabel->operands[1] = dOffset;
         /* Insert the place holder to the growable list */
-        dvmInsertGrowableList(&cUnit->pcReconstructionList, pcrLabel);
+        dvmInsertGrowableList(&cUnit->pcReconstructionList,
+                              (intptr_t) pcrLabel);
     }
     /* Branch to the PC reconstruction code */
     branch->generic.target = (LIR *) pcrLabel;
index 2a53592..6473edb 100644 (file)
@@ -917,7 +917,7 @@ static void genReturnCommon(CompilationUnit *cUnit, MIR *mir)
     pcrLabel->operands[0] = dPC;
     pcrLabel->operands[1] = mir->offset;
     /* Insert the place holder to the growable list */
-    dvmInsertGrowableList(&cUnit->pcReconstructionList, pcrLabel);
+    dvmInsertGrowableList(&cUnit->pcReconstructionList, (intptr_t) pcrLabel);
     /* Branch to the PC reconstruction code */
     branch->generic.target = (LIR *) pcrLabel;
 }
@@ -1161,7 +1161,8 @@ static void genInvokeVirtualCommon(CompilationUnit *cUnit, MIR *mir,
         pcrLabel->operands[0] = dPC;
         pcrLabel->operands[1] = mir->offset;
         /* Insert the place holder to the growable list */
-        dvmInsertGrowableList(&cUnit->pcReconstructionList, pcrLabel);
+        dvmInsertGrowableList(&cUnit->pcReconstructionList,
+                              (intptr_t) pcrLabel);
     }
 
     /* return through lr+2 - punt to the interpreter */
@@ -3013,7 +3014,8 @@ static bool handleFmt35c_3rc(CompilationUnit *cUnit, MIR *mir, BasicBlock *bb,
                 pcrLabel->operands[0] = dPC;
                 pcrLabel->operands[1] = mir->offset;
                 /* Insert the place holder to the growable list */
-                dvmInsertGrowableList(&cUnit->pcReconstructionList, pcrLabel);
+                dvmInsertGrowableList(&cUnit->pcReconstructionList,
+                                      (intptr_t) pcrLabel);
             }
 
             /* return through lr+2 - punt to the interpreter */
@@ -3886,7 +3888,7 @@ static void setupLoopEntryBlock(CompilationUnit *cUnit, BasicBlock *entry,
         (int) (cUnit->method->insns + entry->startOffset);
     pcrLabel->operands[1] = entry->startOffset;
     /* Insert the place holder to the growable list */
-    dvmInsertGrowableList(&cUnit->pcReconstructionList, pcrLabel);
+    dvmInsertGrowableList(&cUnit->pcReconstructionList, (intptr_t) pcrLabel);
 
     /*
      * Next, create two branches - one branch over to the loop body and the
@@ -3939,7 +3941,8 @@ void dvmCompilerMIR2LIR(CompilationUnit *cUnit)
         dvmInitGrowableList(&chainingListByType[i], 2);
     }
 
-    BasicBlock **blockList = cUnit->blockList;
+    GrowableListIterator iterator;
+    dvmGrowableListIteratorInit(&cUnit->blockList, &iterator);
 
     if (cUnit->executionCount) {
         /*
@@ -3976,14 +3979,15 @@ void dvmCompilerMIR2LIR(CompilationUnit *cUnit)
     }
 
     /* Handle the content in each basic block */
-    for (i = 0; i < cUnit->numBlocks; i++) {
-        blockList[i]->visited = true;
+    for (i = 0; ; i++) {
         MIR *mir;
+        BasicBlock *bb = (BasicBlock *) dvmGrowableListIteratorNext(&iterator);
+        if (bb == NULL) break;
 
-        labelList[i].operands[0] = blockList[i]->startOffset;
+        labelList[i].operands[0] = bb->startOffset;
 
-        if (blockList[i]->blockType >= kChainingCellGap) {
-            if (blockList[i]->isFallThroughFromInvoke == true) {
+        if (bb->blockType >= kChainingCellGap) {
+            if (bb->isFallThroughFromInvoke == true) {
                 /* Align this block first since it is a return chaining cell */
                 newLIR0(cUnit, kArmPseudoPseudoAlign4);
             }
@@ -3994,56 +3998,53 @@ void dvmCompilerMIR2LIR(CompilationUnit *cUnit)
             dvmCompilerAppendLIR(cUnit, (LIR *) &labelList[i]);
         }
 
-        if (blockList[i]->blockType == kTraceEntryBlock) {
+        if (bb->blockType == kTraceEntryBlock) {
             labelList[i].opcode = kArmPseudoEntryBlock;
-            if (blockList[i]->firstMIRInsn == NULL) {
+            if (bb->firstMIRInsn == NULL) {
                 continue;
             } else {
-              setupLoopEntryBlock(cUnit, blockList[i],
-                                  &labelList[blockList[i]->fallThrough->id]);
+              setupLoopEntryBlock(cUnit, bb,
+                                  &labelList[bb->fallThrough->id]);
             }
-        } else if (blockList[i]->blockType == kTraceExitBlock) {
+        } else if (bb->blockType == kTraceExitBlock) {
             labelList[i].opcode = kArmPseudoExitBlock;
             goto gen_fallthrough;
-        } else if (blockList[i]->blockType == kDalvikByteCode) {
+        } else if (bb->blockType == kDalvikByteCode) {
             labelList[i].opcode = kArmPseudoNormalBlockLabel;
             /* Reset the register state */
             dvmCompilerResetRegPool(cUnit);
             dvmCompilerClobberAllRegs(cUnit);
             dvmCompilerResetNullCheck(cUnit);
         } else {
-            switch (blockList[i]->blockType) {
+            switch (bb->blockType) {
                 case kChainingCellNormal:
                     labelList[i].opcode = kArmPseudoChainingCellNormal;
                     /* handle the codegen later */
                     dvmInsertGrowableList(
-                        &chainingListByType[kChainingCellNormal], (void *) i);
+                        &chainingListByType[kChainingCellNormal], i);
                     break;
                 case kChainingCellInvokeSingleton:
                     labelList[i].opcode =
                         kArmPseudoChainingCellInvokeSingleton;
                     labelList[i].operands[0] =
-                        (int) blockList[i]->containingMethod;
+                        (int) bb->containingMethod;
                     /* handle the codegen later */
                     dvmInsertGrowableList(
-                        &chainingListByType[kChainingCellInvokeSingleton],
-                        (void *) i);
+                        &chainingListByType[kChainingCellInvokeSingleton], i);
                     break;
                 case kChainingCellInvokePredicted:
                     labelList[i].opcode =
                         kArmPseudoChainingCellInvokePredicted;
                     /* handle the codegen later */
                     dvmInsertGrowableList(
-                        &chainingListByType[kChainingCellInvokePredicted],
-                        (void *) i);
+                        &chainingListByType[kChainingCellInvokePredicted], i);
                     break;
                 case kChainingCellHot:
                     labelList[i].opcode =
                         kArmPseudoChainingCellHot;
                     /* handle the codegen later */
                     dvmInsertGrowableList(
-                        &chainingListByType[kChainingCellHot],
-                        (void *) i);
+                        &chainingListByType[kChainingCellHot], i);
                     break;
                 case kPCReconstruction:
                     /* Make sure exception handling block is next */
@@ -4068,7 +4069,7 @@ void dvmCompilerMIR2LIR(CompilationUnit *cUnit)
                     /* handle the codegen later */
                     dvmInsertGrowableList(
                         &chainingListByType[kChainingCellBackwardBranch],
-                        (void *) i);
+                        i);
                     break;
 #endif
                 default:
@@ -4079,7 +4080,7 @@ void dvmCompilerMIR2LIR(CompilationUnit *cUnit)
 
         ArmLIR *headLIR = NULL;
 
-        for (mir = blockList[i]->firstMIRInsn; mir; mir = mir->next) {
+        for (mir = bb->firstMIRInsn; mir; mir = mir->next) {
 
             dvmCompilerResetRegPool(cUnit);
             if (gDvmJit.disableOpt & (1 << kTrackLiveTemps)) {
@@ -4147,7 +4148,7 @@ void dvmCompilerMIR2LIR(CompilationUnit *cUnit)
                     case kFmt20t:
                     case kFmt30t:
                         notHandled = handleFmt10t_Fmt20t_Fmt30t(cUnit,
-                                  mir, blockList[i], labelList);
+                                  mir, bb, labelList);
                         break;
                     case kFmt10x:
                         notHandled = handleFmt10x(cUnit, mir);
@@ -4176,8 +4177,7 @@ void dvmCompilerMIR2LIR(CompilationUnit *cUnit)
                         notHandled = handleFmt21s(cUnit, mir);
                         break;
                     case kFmt21t:
-                        notHandled = handleFmt21t(cUnit, mir, blockList[i],
-                                                  labelList);
+                        notHandled = handleFmt21t(cUnit, mir, bb, labelList);
                         break;
                     case kFmt22b:
                     case kFmt22s:
@@ -4190,8 +4190,7 @@ void dvmCompilerMIR2LIR(CompilationUnit *cUnit)
                         notHandled = handleFmt22cs(cUnit, mir);
                         break;
                     case kFmt22t:
-                        notHandled = handleFmt22t(cUnit, mir, blockList[i],
-                                                  labelList);
+                        notHandled = handleFmt22t(cUnit, mir, bb, labelList);
                         break;
                     case kFmt22x:
                     case kFmt32x:
@@ -4205,12 +4204,12 @@ void dvmCompilerMIR2LIR(CompilationUnit *cUnit)
                         break;
                     case kFmt3rc:
                     case kFmt35c:
-                        notHandled = handleFmt35c_3rc(cUnit, mir, blockList[i],
+                        notHandled = handleFmt35c_3rc(cUnit, mir, bb,
                                                       labelList);
                         break;
                     case kFmt3rms:
                     case kFmt35ms:
-                        notHandled = handleFmt35ms_3rms(cUnit, mir,blockList[i],
+                        notHandled = handleFmt35ms_3rms(cUnit, mir, bb,
                                                         labelList);
                         break;
                     case kFmt35mi:
@@ -4235,7 +4234,7 @@ void dvmCompilerMIR2LIR(CompilationUnit *cUnit)
             }
         }
 
-        if (blockList[i]->blockType == kTraceEntryBlock) {
+        if (bb->blockType == kTraceEntryBlock) {
             dvmCompilerAppendLIR(cUnit,
                                  (LIR *) cUnit->loopAnalysis->branchToBody);
             dvmCompilerAppendLIR(cUnit,
@@ -4256,9 +4255,9 @@ gen_fallthrough:
          * Check if the block is terminated due to trace length constraint -
          * insert an unconditional branch to the chaining cell.
          */
-        if (blockList[i]->needFallThroughBranch) {
+        if (bb->needFallThroughBranch) {
             genUnconditionalBranch(cUnit,
-                                   &labelList[blockList[i]->fallThrough->id]);
+                                   &labelList[bb->fallThrough->id]);
         }
 
     }
@@ -4279,6 +4278,9 @@ gen_fallthrough:
 
         for (j = 0; j < chainingListByType[i].numUsed; j++) {
             int blockId = blockIdList[j];
+            BasicBlock *chainingBlock =
+                (BasicBlock *) dvmGrowableListGetElement(&cUnit->blockList,
+                                                         blockId);
 
             /* Align this chaining cell first */
             newLIR0(cUnit, kArmPseudoPseudoAlign4);
@@ -4287,30 +4289,28 @@ gen_fallthrough:
             dvmCompilerAppendLIR(cUnit, (LIR *) &labelList[blockId]);
 
 
-            switch (blockList[blockId]->blockType) {
+            switch (chainingBlock->blockType) {
                 case kChainingCellNormal:
-                    handleNormalChainingCell(cUnit,
-                      blockList[blockId]->startOffset);
+                    handleNormalChainingCell(cUnit, chainingBlock->startOffset);
                     break;
                 case kChainingCellInvokeSingleton:
                     handleInvokeSingletonChainingCell(cUnit,
-                        blockList[blockId]->containingMethod);
+                        chainingBlock->containingMethod);
                     break;
                 case kChainingCellInvokePredicted:
                     handleInvokePredictedChainingCell(cUnit);
                     break;
                 case kChainingCellHot:
-                    handleHotChainingCell(cUnit,
-                        blockList[blockId]->startOffset);
+                    handleHotChainingCell(cUnit, chainingBlock->startOffset);
                     break;
 #if defined(WITH_SELF_VERIFICATION) || defined(WITH_JIT_TUNING)
                 case kChainingCellBackwardBranch:
                     handleBackwardBranchChainingCell(cUnit,
-                        blockList[blockId]->startOffset);
+                        chainingBlock->startOffset);
                     break;
 #endif
                 default:
-                    LOGE("Bad blocktype %d", blockList[blockId]->blockType);
+                    LOGE("Bad blocktype %d", chainingBlock->blockType);
                     dvmCompilerAbort(cUnit);
             }
         }
index 5d8e3d6..fb47b03 100644 (file)
@@ -3682,7 +3682,7 @@ GOTO_TARGET(returnFromMethod)
 #endif
 
         /* back up to previous frame and see if we hit a break */
-        fp = saveArea->prevFrame;
+        fp = (u4*)saveArea->prevFrame;
         assert(fp != NULL);
         if (dvmIsBreakFrame(fp)) {
             /* bail without popping the method frame from stack */
@@ -3794,7 +3794,7 @@ GOTO_TARGET(exceptionThrown)
          * the "catch" blocks.
          */
         catchRelPc = dvmFindCatchBlock(self, pc - curMethod->insns,
-                    exception, false, (void*)&fp);
+                    exception, false, (void**)(void*)&fp);
 
         /*
          * Restore the stack bounds after an overflow.  This isn't going to
@@ -4027,7 +4027,7 @@ GOTO_TARGET(invokeMethod, bool methodCallRange, const Method* _methodToCall,
             curMethod = methodToCall;
             methodClassDex = curMethod->clazz->pDvmDex;
             pc = methodToCall->insns;
-            fp = self->curFrame = newFp;
+            self->curFrame = fp = newFp;
 #ifdef EASY_GDB
             debugSaveArea = SAVEAREA_FROM_FP(newFp);
 #endif
index 587dcd5..87995e9 100644 (file)
@@ -1808,7 +1808,7 @@ GOTO_TARGET(returnFromMethod)
 #endif
 
         /* back up to previous frame and see if we hit a break */
-        fp = saveArea->prevFrame;
+        fp = (u4*)saveArea->prevFrame;
         assert(fp != NULL);
         if (dvmIsBreakFrame(fp)) {
             /* bail without popping the method frame from stack */
@@ -1920,7 +1920,7 @@ GOTO_TARGET(exceptionThrown)
          * the "catch" blocks.
          */
         catchRelPc = dvmFindCatchBlock(self, pc - curMethod->insns,
-                    exception, false, (void*)&fp);
+                    exception, false, (void**)(void*)&fp);
 
         /*
          * Restore the stack bounds after an overflow.  This isn't going to
@@ -2153,7 +2153,7 @@ GOTO_TARGET(invokeMethod, bool methodCallRange, const Method* _methodToCall,
             curMethod = methodToCall;
             methodClassDex = curMethod->clazz->pDvmDex;
             pc = methodToCall->insns;
-            fp = self->curFrame = newFp;
+            self->curFrame = fp = newFp;
 #ifdef EASY_GDB
             debugSaveArea = SAVEAREA_FROM_FP(newFp);
 #endif
index 8a7a1d5..b5f616e 100644 (file)
@@ -1821,7 +1821,7 @@ GOTO_TARGET(returnFromMethod)
 #endif
 
         /* back up to previous frame and see if we hit a break */
-        fp = saveArea->prevFrame;
+        fp = (u4*)saveArea->prevFrame;
         assert(fp != NULL);
         if (dvmIsBreakFrame(fp)) {
             /* bail without popping the method frame from stack */
@@ -1933,7 +1933,7 @@ GOTO_TARGET(exceptionThrown)
          * the "catch" blocks.
          */
         catchRelPc = dvmFindCatchBlock(self, pc - curMethod->insns,
-                    exception, false, (void*)&fp);
+                    exception, false, (void**)(void*)&fp);
 
         /*
          * Restore the stack bounds after an overflow.  This isn't going to
@@ -2166,7 +2166,7 @@ GOTO_TARGET(invokeMethod, bool methodCallRange, const Method* _methodToCall,
             curMethod = methodToCall;
             methodClassDex = curMethod->clazz->pDvmDex;
             pc = methodToCall->insns;
-            fp = self->curFrame = newFp;
+            self->curFrame = fp = newFp;
 #ifdef EASY_GDB
             debugSaveArea = SAVEAREA_FROM_FP(newFp);
 #endif