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