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