Home | History | Annotate | Download | only in compiler
      1 /*
      2  * Copyright (C) 2009 The Android Open Source Project
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 #ifndef DALVIK_VM_COMPILER_IR_H_
     18 #define DALVIK_VM_COMPILER_IR_H_
     19 
     20 #include "codegen/Optimizer.h"
     21 #ifdef ARCH_IA32
     22 #include "CompilerUtility.h"
     23 #endif
     24 
     25 typedef enum RegisterClass {
     26     kCoreReg,
     27     kFPReg,
     28     kAnyReg,
     29 } RegisterClass;
     30 
     31 typedef enum RegLocationType {
     32     kLocDalvikFrame = 0,
     33     kLocPhysReg,
     34     kLocRetval,          // Return region in interpState
     35     kLocSpill,
     36 } RegLocationType;
     37 
     38 typedef struct RegLocation {
     39     RegLocationType location:2;
     40     unsigned wide:1;
     41     unsigned fp:1;      // Hint for float/double
     42     u1 lowReg:6;        // First physical register
     43     u1 highReg:6;       // 2nd physical register (if wide)
     44     s2 sRegLow;         // SSA name for low Dalvik word
     45 } RegLocation;
     46 
     47 #define INVALID_SREG (-1)
     48 #define INVALID_REG (0x3F)
     49 
     50 typedef enum BBType {
     51     /* For coding convenience reasons chaining cell types should appear first */
     52     kChainingCellNormal = 0,
     53     kChainingCellHot,
     54     kChainingCellInvokeSingleton,
     55     kChainingCellInvokePredicted,
     56     kChainingCellBackwardBranch,
     57     kChainingCellGap,
     58     /* Don't insert new fields between Gap and Last */
     59     kChainingCellLast = kChainingCellGap + 1,
     60     kEntryBlock,
     61     kDalvikByteCode,
     62     kExitBlock,
     63     kPCReconstruction,
     64     kExceptionHandling,
     65     kCatchEntry,
     66 } BBType;
     67 
     68 typedef enum JitMode {
     69     kJitTrace = 0, // Acyclic - all instructions come from the trace descriptor
     70     kJitLoop,      // Cycle - trace descriptor is used as a hint
     71     kJitMethod,    // Whole method
     72 } JitMode;
     73 
     74 typedef struct ChainCellCounts {
     75     union {
     76         u1 count[kChainingCellLast]; /* include one more space for the gap # */
     77         u4 dummyForAlignment;
     78     } u;
     79 } ChainCellCounts;
     80 
     81 typedef struct LIR {
     82     int offset;
     83     struct LIR *next;
     84     struct LIR *prev;
     85     struct LIR *target;
     86 } LIR;
     87 
     88 enum ExtendedMIROpcode {
     89     kMirOpFirst = kNumPackedOpcodes,
     90     kMirOpPhi = kMirOpFirst,
     91     kMirOpNullNRangeUpCheck,
     92     kMirOpNullNRangeDownCheck,
     93     kMirOpLowerBound,
     94     kMirOpPunt,
     95     kMirOpCheckInlinePrediction,        // Gen checks for predicted inlining
     96     kMirOpLast,
     97 };
     98 
     99 struct SSARepresentation;
    100 
    101 typedef enum {
    102     kMIRIgnoreNullCheck = 0,
    103     kMIRNullCheckOnly,
    104     kMIRIgnoreRangeCheck,
    105     kMIRRangeCheckOnly,
    106     kMIRInlined,                        // Invoke is inlined (ie dead)
    107     kMIRInlinedPred,                    // Invoke is inlined via prediction
    108     kMIRCallee,                         // Instruction is inlined from callee
    109     kMIRInvokeMethodJIT,                // Callee is JIT'ed as a whole method
    110 } MIROptimizationFlagPositons;
    111 
    112 #define MIR_IGNORE_NULL_CHECK           (1 << kMIRIgnoreNullCheck)
    113 #define MIR_NULL_CHECK_ONLY             (1 << kMIRNullCheckOnly)
    114 #define MIR_IGNORE_RANGE_CHECK          (1 << kMIRIgnoreRangeCheck)
    115 #define MIR_RANGE_CHECK_ONLY            (1 << kMIRRangeCheckOnly)
    116 #define MIR_INLINED                     (1 << kMIRInlined)
    117 #define MIR_INLINED_PRED                (1 << kMIRInlinedPred)
    118 #define MIR_CALLEE                      (1 << kMIRCallee)
    119 #define MIR_INVOKE_METHOD_JIT           (1 << kMIRInvokeMethodJIT)
    120 
    121 typedef struct CallsiteInfo {
    122     const char *classDescriptor;
    123     Object *classLoader;
    124     const Method *method;
    125     LIR *misPredBranchOver;
    126 } CallsiteInfo;
    127 
    128 typedef struct MIR {
    129     DecodedInstruction dalvikInsn;
    130     unsigned int width;
    131     unsigned int offset;
    132     struct MIR *prev;
    133     struct MIR *next;
    134     struct SSARepresentation *ssaRep;
    135     int OptimizationFlags;
    136     int seqNum;
    137     union {
    138         // Used by the inlined insn from the callee to find the mother method
    139         const Method *calleeMethod;
    140         // Used by the inlined invoke to find the class and method pointers
    141         CallsiteInfo *callsiteInfo;
    142     } meta;
    143 } MIR;
    144 
    145 struct BasicBlockDataFlow;
    146 
    147 /* For successorBlockList */
    148 typedef enum BlockListType {
    149     kNotUsed = 0,
    150     kCatch,
    151     kPackedSwitch,
    152     kSparseSwitch,
    153 } BlockListType;
    154 
    155 typedef struct BasicBlock {
    156     int id;
    157     bool visited;
    158     bool hidden;
    159     unsigned int startOffset;
    160     const Method *containingMethod;     // For blocks from the callee
    161     BBType blockType;
    162     bool needFallThroughBranch;         // For blocks ended due to length limit
    163     bool isFallThroughFromInvoke;       // True means the block needs alignment
    164     MIR *firstMIRInsn;
    165     MIR *lastMIRInsn;
    166     struct BasicBlock *fallThrough;
    167     struct BasicBlock *taken;
    168     struct BasicBlock *iDom;            // Immediate dominator
    169     struct BasicBlockDataFlow *dataFlowInfo;
    170     BitVector *predecessors;
    171     BitVector *dominators;
    172     BitVector *iDominated;              // Set nodes being immediately dominated
    173     BitVector *domFrontier;             // Dominance frontier
    174     struct {                            // For one-to-many successors like
    175         BlockListType blockListType;    // switch and exception handling
    176         GrowableList blocks;
    177     } successorBlockList;
    178 } BasicBlock;
    179 
    180 /*
    181  * The "blocks" field in "successorBlockList" points to an array of
    182  * elements with the type "SuccessorBlockInfo".
    183  * For catch blocks, key is type index for the exception.
    184  * For swtich blocks, key is the case value.
    185  */
    186 typedef struct SuccessorBlockInfo {
    187     BasicBlock *block;
    188     int key;
    189 } SuccessorBlockInfo;
    190 
    191 struct LoopAnalysis;
    192 struct RegisterPool;
    193 
    194 typedef enum AssemblerStatus {
    195     kSuccess,
    196     kRetryAll,
    197     kRetryHalve
    198 } AssemblerStatus;
    199 
    200 typedef struct CompilationUnit {
    201     int numInsts;
    202     int numBlocks;
    203     GrowableList blockList;
    204     const Method *method;
    205 #ifdef ARCH_IA32
    206     int exceptionBlockId;               // the block corresponding to exception handling
    207 #endif
    208     const JitTraceDescription *traceDesc;
    209     LIR *firstLIRInsn;
    210     LIR *lastLIRInsn;
    211     LIR *literalList;                   // Constants
    212     LIR *classPointerList;              // Relocatable
    213     int numClassPointers;
    214     LIR *chainCellOffsetLIR;
    215     GrowableList pcReconstructionList;
    216     int headerSize;                     // bytes before the first code ptr
    217     int dataOffset;                     // starting offset of literal pool
    218     int totalSize;                      // header + code size
    219     AssemblerStatus assemblerStatus;    // Success or fix and retry
    220     int assemblerRetries;               // How many times tried to fix assembly
    221     unsigned char *codeBuffer;
    222     void *baseAddr;
    223     bool printMe;
    224     bool allSingleStep;
    225     bool hasClassLiterals;              // Contains class ptrs used as literals
    226     bool hasLoop;                       // Contains a loop
    227     bool hasInvoke;                     // Contains an invoke instruction
    228     bool heapMemOp;                     // Mark mem ops for self verification
    229     bool usesLinkRegister;              // For self-verification only
    230     int profileCodeSize;                // Size of the profile prefix in bytes
    231     int numChainingCells[kChainingCellGap];
    232     LIR *firstChainingLIR[kChainingCellGap];
    233     LIR *chainingCellBottom;
    234     struct RegisterPool *regPool;
    235     int optRound;                       // round number to tell an LIR's age
    236     jmp_buf *bailPtr;
    237     JitInstructionSetType instructionSet;
    238     /* Number of total regs used in the whole cUnit after SSA transformation */
    239     int numSSARegs;
    240     /* Map SSA reg i to the Dalvik[15..0]/Sub[31..16] pair. */
    241     GrowableList *ssaToDalvikMap;
    242 
    243     /* The following are new data structures to support SSA representations */
    244     /* Map original Dalvik reg i to the SSA[15..0]/Sub[31..16] pair */
    245     int *dalvikToSSAMap;                // length == method->registersSize
    246     BitVector *isConstantV;             // length == numSSAReg
    247     int *constantValues;                // length == numSSAReg
    248 
    249     /* Data structure for loop analysis and optimizations */
    250     struct LoopAnalysis *loopAnalysis;
    251 
    252     /* Map SSA names to location */
    253     RegLocation *regLocation;
    254     int sequenceNumber;
    255 
    256     /*
    257      * Set to the Dalvik PC of the switch instruction if it has more than
    258      * MAX_CHAINED_SWITCH_CASES cases.
    259      */
    260     const u2 *switchOverflowPad;
    261 
    262     JitMode jitMode;
    263     int numReachableBlocks;
    264     int numDalvikRegisters;             // method->registersSize + inlined
    265     BasicBlock *entryBlock;
    266     BasicBlock *exitBlock;
    267     BasicBlock *puntBlock;              // punting to interp for exceptions
    268     BasicBlock *backChainBlock;         // for loop-trace
    269     BasicBlock *curBlock;
    270     BasicBlock *nextCodegenBlock;       // for extended trace codegen
    271     GrowableList dfsOrder;
    272     GrowableList domPostOrderTraversal;
    273     BitVector *tryBlockAddr;
    274     BitVector **defBlockMatrix;         // numDalvikRegister x numBlocks
    275     BitVector *tempBlockV;
    276     BitVector *tempDalvikRegisterV;
    277     BitVector *tempSSARegisterV;        // numSSARegs
    278     bool printSSANames;
    279     void *blockLabelList;
    280     bool quitLoopMode;                  // cold path/complex bytecode
    281 } CompilationUnit;
    282 
    283 #if defined(WITH_SELF_VERIFICATION)
    284 #define HEAP_ACCESS_SHADOW(_state) cUnit->heapMemOp = _state
    285 #else
    286 #define HEAP_ACCESS_SHADOW(_state)
    287 #endif
    288 
    289 BasicBlock *dvmCompilerNewBB(BBType blockType, int blockId);
    290 
    291 void dvmCompilerAppendMIR(BasicBlock *bb, MIR *mir);
    292 
    293 void dvmCompilerPrependMIR(BasicBlock *bb, MIR *mir);
    294 
    295 void dvmCompilerInsertMIRAfter(BasicBlock *bb, MIR *currentMIR, MIR *newMIR);
    296 
    297 void dvmCompilerAppendLIR(CompilationUnit *cUnit, LIR *lir);
    298 
    299 void dvmCompilerInsertLIRBefore(LIR *currentLIR, LIR *newLIR);
    300 
    301 void dvmCompilerInsertLIRAfter(LIR *currentLIR, LIR *newLIR);
    302 
    303 void dvmCompilerAbort(CompilationUnit *cUnit);
    304 
    305 /* Debug Utilities */
    306 void dvmCompilerDumpCompilationUnit(CompilationUnit *cUnit);
    307 
    308 #endif  // DALVIK_VM_COMPILER_IR_H_
    309