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_H_
     18 #define DALVIK_VM_COMPILER_H_
     19 
     20 #include <setjmp.h>
     21 #include "Thread.h"
     22 
     23 /*
     24  * Uncomment the following to enable JIT signature breakpoint
     25  * #define SIGNATURE_BREAKPOINT
     26  */
     27 
     28 #define COMPILER_WORK_QUEUE_SIZE        100
     29 #define COMPILER_IC_PATCH_QUEUE_SIZE    64
     30 #define COMPILER_PC_OFFSET_SIZE         100
     31 
     32 /* Architectural-independent parameters for predicted chains */
     33 #define PREDICTED_CHAIN_CLAZZ_INIT       0
     34 #define PREDICTED_CHAIN_METHOD_INIT      0
     35 #define PREDICTED_CHAIN_COUNTER_INIT     0
     36 /* A fake value which will avoid initialization and won't match any class */
     37 #define PREDICTED_CHAIN_FAKE_CLAZZ       0xdeadc001
     38 /* Has to be positive */
     39 #define PREDICTED_CHAIN_COUNTER_AVOID    0x7fffffff
     40 /* Rechain after this many misses - shared globally and has to be positive */
     41 #define PREDICTED_CHAIN_COUNTER_RECHAIN  8192
     42 
     43 #define COMPILER_TRACED(X)
     44 #define COMPILER_TRACEE(X)
     45 #define COMPILER_TRACE_CHAINING(X)
     46 
     47 /* Macro to change the permissions applied to a chunk of the code cache */
     48 #define PROTECT_CODE_CACHE_ATTRS       (PROT_READ | PROT_EXEC)
     49 #define UNPROTECT_CODE_CACHE_ATTRS     (PROT_READ | PROT_EXEC | PROT_WRITE)
     50 
     51 /* Acquire the lock before removing PROT_WRITE from the specified mem region */
     52 #define UNPROTECT_CODE_CACHE(addr, size)                                       \
     53     {                                                                          \
     54         dvmLockMutex(&gDvmJit.codeCacheProtectionLock);                        \
     55         mprotect((void *) (((intptr_t) (addr)) & ~gDvmJit.pageSizeMask),       \
     56                  (size) + (((intptr_t) (addr)) & gDvmJit.pageSizeMask),        \
     57                  (UNPROTECT_CODE_CACHE_ATTRS));                                \
     58     }
     59 
     60 /* Add the PROT_WRITE to the specified memory region then release the lock */
     61 #define PROTECT_CODE_CACHE(addr, size)                                         \
     62     {                                                                          \
     63         mprotect((void *) (((intptr_t) (addr)) & ~gDvmJit.pageSizeMask),       \
     64                  (size) + (((intptr_t) (addr)) & gDvmJit.pageSizeMask),        \
     65                  (PROTECT_CODE_CACHE_ATTRS));                                  \
     66         dvmUnlockMutex(&gDvmJit.codeCacheProtectionLock);                      \
     67     }
     68 
     69 #define SINGLE_STEP_OP(opcode)                                                 \
     70     (gDvmJit.includeSelectedOp !=                                              \
     71      ((gDvmJit.opList[opcode >> 3] & (1 << (opcode & 0x7))) != 0))
     72 
     73 typedef enum JitInstructionSetType {
     74     DALVIK_JIT_NONE = 0,
     75     DALVIK_JIT_ARM,
     76     DALVIK_JIT_THUMB,
     77     DALVIK_JIT_THUMB2,
     78     DALVIK_JIT_IA32,
     79     DALVIK_JIT_MIPS
     80 } JitInstructionSetType;
     81 
     82 /* Description of a compiled trace. */
     83 typedef struct JitTranslationInfo {
     84     void *codeAddress;
     85     JitInstructionSetType instructionSet;
     86     int profileCodeSize;
     87     bool discardResult;         // Used for debugging divergence and IC patching
     88     bool methodCompilationAborted;  // Cannot compile the whole method
     89     Thread *requestingThread;   // For debugging purpose
     90     int cacheVersion;           // Used to identify stale trace requests
     91 } JitTranslationInfo;
     92 
     93 typedef enum WorkOrderKind {
     94     kWorkOrderInvalid = 0,      // Should never see by the backend
     95     kWorkOrderMethod = 1,       // Work is to compile a whole method
     96     kWorkOrderTrace = 2,        // Work is to compile code fragment(s)
     97     kWorkOrderTraceDebug = 3,   // Work is to compile/debug code fragment(s)
     98     kWorkOrderProfileMode = 4,  // Change profiling mode
     99 } WorkOrderKind;
    100 
    101 typedef struct CompilerWorkOrder {
    102     const u2* pc;
    103     WorkOrderKind kind;
    104     void* info;
    105     JitTranslationInfo result;
    106     jmp_buf *bailPtr;
    107 } CompilerWorkOrder;
    108 
    109 /* Chain cell for predicted method invocation */
    110 typedef struct PredictedChainingCell {
    111     u4 branch;                  /* Branch to chained destination */
    112 #ifdef __mips__
    113     u4 delay_slot;              /* nop goes here */
    114 #elif defined(ARCH_IA32)
    115     u4 branch2;                 /* IA32 branch instr may be > 32 bits */
    116 #endif
    117     const ClassObject *clazz;   /* key for prediction */
    118     const Method *method;       /* to lookup native PC from dalvik PC */
    119     const ClassObject *stagedClazz;   /* possible next key for prediction */
    120 } PredictedChainingCell;
    121 
    122 /* Work order for inline cache patching */
    123 typedef struct ICPatchWorkOrder {
    124     PredictedChainingCell *cellAddr;    /* Address to be patched */
    125     PredictedChainingCell cellContent;  /* content of the new cell */
    126     const char *classDescriptor;        /* Descriptor of the class object */
    127     Object *classLoader;                /* Class loader */
    128     u4 serialNumber;                    /* Serial # (for verification only) */
    129 } ICPatchWorkOrder;
    130 
    131 /*
    132  * Trace description as will appear in the translation cache.  Note
    133  * flexible array at end, as these will be of variable size.  To
    134  * conserve space in the translation cache, total length of JitTraceRun
    135  * array must be recomputed via seqential scan if needed.
    136  */
    137 typedef struct {
    138     const Method* method;
    139     JitTraceRun trace[0];       // Variable-length trace descriptors
    140 } JitTraceDescription;
    141 
    142 typedef enum JitMethodAttributes {
    143     kIsCallee = 0,      /* Code is part of a callee (invoked by a hot trace) */
    144     kIsHot,             /* Code is part of a hot trace */
    145     kIsLeaf,            /* Method is leaf */
    146     kIsEmpty,           /* Method is empty */
    147     kIsThrowFree,       /* Method doesn't throw */
    148     kIsGetter,          /* Method fits the getter pattern */
    149     kIsSetter,          /* Method fits the setter pattern */
    150     kCannotCompile,     /* Method cannot be compiled */
    151 } JitMethodAttributes;
    152 
    153 #define METHOD_IS_CALLEE        (1 << kIsCallee)
    154 #define METHOD_IS_HOT           (1 << kIsHot)
    155 #define METHOD_IS_LEAF          (1 << kIsLeaf)
    156 #define METHOD_IS_EMPTY         (1 << kIsEmpty)
    157 #define METHOD_IS_THROW_FREE    (1 << kIsThrowFree)
    158 #define METHOD_IS_GETTER        (1 << kIsGetter)
    159 #define METHOD_IS_SETTER        (1 << kIsSetter)
    160 #define METHOD_CANNOT_COMPILE   (1 << kCannotCompile)
    161 
    162 /* Vectors to provide optimization hints */
    163 typedef enum JitOptimizationHints {
    164     kJitOptNoLoop = 0,          // Disable loop formation/optimization
    165 } JitOptimizationHints;
    166 
    167 #define JIT_OPT_NO_LOOP         (1 << kJitOptNoLoop)
    168 
    169 /* Customized node traversal orders for different needs */
    170 typedef enum DataFlowAnalysisMode {
    171     kAllNodes = 0,              // All nodes
    172     kReachableNodes,            // All reachable nodes
    173     kPreOrderDFSTraversal,      // Depth-First-Search / Pre-Order
    174     kPostOrderDFSTraversal,     // Depth-First-Search / Post-Order
    175     kPostOrderDOMTraversal,     // Dominator tree / Post-Order
    176 } DataFlowAnalysisMode;
    177 
    178 typedef struct CompilerMethodStats {
    179     const Method *method;       // Used as hash entry signature
    180     int dalvikSize;             // # of bytes for dalvik bytecodes
    181     int compiledDalvikSize;     // # of compiled dalvik bytecodes
    182     int nativeSize;             // # of bytes for produced native code
    183     int attributes;             // attribute vector
    184 } CompilerMethodStats;
    185 
    186 struct CompilationUnit;
    187 struct BasicBlock;
    188 struct SSARepresentation;
    189 struct GrowableList;
    190 struct JitEntry;
    191 struct MIR;
    192 
    193 bool dvmCompilerSetupCodeCache(void);
    194 bool dvmCompilerArchInit(void);
    195 void dvmCompilerArchDump(void);
    196 bool dvmCompilerStartup(void);
    197 void dvmCompilerShutdown(void);
    198 void dvmCompilerForceWorkEnqueue(const u2* pc, WorkOrderKind kind, void* info);
    199 bool dvmCompilerWorkEnqueue(const u2* pc, WorkOrderKind kind, void* info);
    200 void *dvmCheckCodeCache(void *method);
    201 CompilerMethodStats *dvmCompilerAnalyzeMethodBody(const Method *method,
    202                                                   bool isCallee);
    203 bool dvmCompilerCanIncludeThisInstruction(const Method *method,
    204                                           const DecodedInstruction *insn);
    205 bool dvmCompileMethod(const Method *method, JitTranslationInfo *info);
    206 bool dvmCompileTrace(JitTraceDescription *trace, int numMaxInsts,
    207                      JitTranslationInfo *info, jmp_buf *bailPtr, int optHints);
    208 void dvmCompilerDumpStats(void);
    209 void dvmCompilerDrainQueue(void);
    210 void dvmJitUnchainAll(void);
    211 void dvmJitScanAllClassPointers(void (*callback)(void *ptr));
    212 void dvmCompilerSortAndPrintTraceProfiles(void);
    213 void dvmCompilerPerformSafePointChecks(void);
    214 void dvmCompilerInlineMIR(struct CompilationUnit *cUnit,
    215                           JitTranslationInfo *info);
    216 void dvmInitializeSSAConversion(struct CompilationUnit *cUnit);
    217 int dvmConvertSSARegToDalvik(const struct CompilationUnit *cUnit, int ssaReg);
    218 bool dvmCompilerLoopOpt(struct CompilationUnit *cUnit);
    219 void dvmCompilerInsertBackwardChaining(struct CompilationUnit *cUnit);
    220 void dvmCompilerNonLoopAnalysis(struct CompilationUnit *cUnit);
    221 bool dvmCompilerFindLocalLiveIn(struct CompilationUnit *cUnit,
    222                                 struct BasicBlock *bb);
    223 bool dvmCompilerDoSSAConversion(struct CompilationUnit *cUnit,
    224                                 struct BasicBlock *bb);
    225 bool dvmCompilerDoConstantPropagation(struct CompilationUnit *cUnit,
    226                                       struct BasicBlock *bb);
    227 bool dvmCompilerFindInductionVariables(struct CompilationUnit *cUnit,
    228                                        struct BasicBlock *bb);
    229 /* Clear the visited flag for each BB */
    230 bool dvmCompilerClearVisitedFlag(struct CompilationUnit *cUnit,
    231                                  struct BasicBlock *bb);
    232 char *dvmCompilerGetDalvikDisassembly(const DecodedInstruction *insn,
    233                                       const char *note);
    234 char *dvmCompilerFullDisassembler(const struct CompilationUnit *cUnit,
    235                                   const struct MIR *mir);
    236 char *dvmCompilerGetSSAString(struct CompilationUnit *cUnit,
    237                               struct SSARepresentation *ssaRep);
    238 void dvmCompilerDataFlowAnalysisDispatcher(struct CompilationUnit *cUnit,
    239                 bool (*func)(struct CompilationUnit *, struct BasicBlock *),
    240                 DataFlowAnalysisMode dfaMode,
    241                 bool isIterative);
    242 void dvmCompilerMethodSSATransformation(struct CompilationUnit *cUnit);
    243 bool dvmCompilerBuildLoop(struct CompilationUnit *cUnit);
    244 void dvmCompilerUpdateGlobalState(void);
    245 JitTraceDescription *dvmCopyTraceDescriptor(const u2 *pc,
    246                                             const struct JitEntry *desc);
    247 extern "C" void *dvmCompilerGetInterpretTemplate();
    248 JitInstructionSetType dvmCompilerGetInterpretTemplateSet();
    249 u8 dvmGetRegResourceMask(int reg);
    250 void dvmDumpCFG(struct CompilationUnit *cUnit, const char *dirPrefix);
    251 bool dvmIsOpcodeSupportedByJit(Opcode opcode);
    252 
    253 #endif  // DALVIK_VM_COMPILER_H_
    254