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 #include <Thread.h>
     18 #include <setjmp.h>
     19 
     20 #ifndef _DALVIK_VM_COMPILER
     21 #define _DALVIK_VM_COMPILER
     22 
     23 /*
     24  * Uncomment the following to enable JIT signature breakpoint
     25  * #define SIGNATURE_BREAKPOINT
     26  */
     27 
     28 #define MAX_JIT_RUN_LEN                 64
     29 #define COMPILER_WORK_QUEUE_SIZE        100
     30 #define COMPILER_IC_PATCH_QUEUE_SIZE    64
     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 #if !defined(WITH_JIT_TUNING)
     49 #define PROTECT_CODE_CACHE_ATTRS       (PROT_READ | PROT_EXEC)
     50 #define UNPROTECT_CODE_CACHE_ATTRS     (PROT_READ | PROT_EXEC | PROT_WRITE)
     51 #else
     52 /* When doing JIT profiling always grant the write permission */
     53 #define PROTECT_CODE_CACHE_ATTRS       (PROT_READ | PROT_EXEC |                \
     54                                   (gDvmJit.profile ? PROT_WRITE : 0))
     55 #define UNPROTECT_CODE_CACHE_ATTRS     (PROT_READ | PROT_EXEC | PROT_WRITE)
     56 #endif
     57 
     58 /* Acquire the lock before removing PROT_WRITE from the specified mem region */
     59 #define UNPROTECT_CODE_CACHE(addr, size)                                       \
     60     {                                                                          \
     61         dvmLockMutex(&gDvmJit.codeCacheProtectionLock);                        \
     62         mprotect((void *) (((intptr_t) (addr)) & ~gDvmJit.pageSizeMask),       \
     63                  (size) + (((intptr_t) (addr)) & gDvmJit.pageSizeMask),        \
     64                  (UNPROTECT_CODE_CACHE_ATTRS));                                \
     65     }
     66 
     67 /* Add the PROT_WRITE to the specified memory region then release the lock */
     68 #define PROTECT_CODE_CACHE(addr, size)                                         \
     69     {                                                                          \
     70         mprotect((void *) (((intptr_t) (addr)) & ~gDvmJit.pageSizeMask),       \
     71                  (size) + (((intptr_t) (addr)) & gDvmJit.pageSizeMask),        \
     72                  (PROTECT_CODE_CACHE_ATTRS));                                  \
     73         dvmUnlockMutex(&gDvmJit.codeCacheProtectionLock);                      \
     74     }
     75 
     76 #define SINGLE_STEP_OP(opcode)                                                 \
     77     (gDvmJit.includeSelectedOp !=                                              \
     78      ((gDvmJit.opList[opcode >> 3] & (1 << (opcode & 0x7))) != 0))
     79 
     80 typedef enum JitInstructionSetType {
     81     DALVIK_JIT_NONE = 0,
     82     DALVIK_JIT_ARM,
     83     DALVIK_JIT_THUMB,
     84     DALVIK_JIT_THUMB2,
     85     DALVIK_JIT_THUMB2EE,
     86     DALVIK_JIT_X86
     87 } JitInstructionSetType;
     88 
     89 /* Description of a compiled trace. */
     90 typedef struct JitTranslationInfo {
     91     void *codeAddress;
     92     JitInstructionSetType instructionSet;
     93     bool discardResult;         // Used for debugging divergence and IC patching
     94     bool methodCompilationAborted;  // Cannot compile the whole method
     95     Thread *requestingThread;   // For debugging purpose
     96 } JitTranslationInfo;
     97 
     98 typedef enum WorkOrderKind {
     99     kWorkOrderInvalid = 0,      // Should never see by the backend
    100     kWorkOrderMethod = 1,       // Work is to compile a whole method
    101     kWorkOrderTrace = 2,        // Work is to compile code fragment(s)
    102     kWorkOrderTraceDebug = 3,   // Work is to compile/debug code fragment(s)
    103 } WorkOrderKind;
    104 
    105 typedef struct CompilerWorkOrder {
    106     const u2* pc;
    107     WorkOrderKind kind;
    108     void* info;
    109     JitTranslationInfo result;
    110     jmp_buf *bailPtr;
    111 } CompilerWorkOrder;
    112 
    113 /* Chain cell for predicted method invocation */
    114 typedef struct PredictedChainingCell {
    115     u4 branch;                  /* Branch to chained destination */
    116     const ClassObject *clazz;   /* key for prediction */
    117     const Method *method;       /* to lookup native PC from dalvik PC */
    118     const ClassObject *stagedClazz;   /* possible next key for prediction */
    119 } PredictedChainingCell;
    120 
    121 /* Work order for inline cache patching */
    122 typedef struct ICPatchWorkOrder {
    123     PredictedChainingCell *cellAddr;    /* Address to be patched */
    124     PredictedChainingCell cellContent;  /* content of the new cell */
    125 } ICPatchWorkOrder;
    126 
    127 /* States of the dbg interpreter when serving a JIT-related request */
    128 typedef enum JitState {
    129     /* Entering states in the debug interpreter */
    130     kJitNot = 0,               // Non-JIT related reasons */
    131     kJitTSelectRequest = 1,    // Request a trace (subject to filtering)
    132     kJitTSelectRequestHot = 2, // Request a hot trace (bypass the filter)
    133     kJitSelfVerification = 3,  // Self Verification Mode
    134 
    135     /* Operational states in the debug interpreter */
    136     kJitTSelect = 4,           // Actively selecting a trace
    137     kJitTSelectEnd = 5,        // Done with the trace - wrap it up
    138     kJitSingleStep = 6,        // Single step interpretation
    139     kJitSingleStepEnd = 7,     // Done with single step, ready return to mterp
    140     kJitDone = 8,              // Ready to leave the debug interpreter
    141 } JitState;
    142 
    143 #if defined(WITH_SELF_VERIFICATION)
    144 typedef enum SelfVerificationState {
    145     kSVSIdle = 0,           // Idle
    146     kSVSStart = 1,          // Shadow space set up, running compiled code
    147     kSVSPunt = 2,           // Exiting compiled code by punting
    148     kSVSSingleStep = 3,     // Exiting compiled code by single stepping
    149     kSVSNoProfile = 4,      // Exiting compiled code and don't collect profiles
    150     kSVSTraceSelect = 5,    // Exiting compiled code and compile the next pc
    151     kSVSNormal = 6,         // Exiting compiled code normally
    152     kSVSNoChain = 7,        // Exiting compiled code by no chain
    153     kSVSBackwardBranch = 8, // Exiting compiled code with backward branch trace
    154     kSVSDebugInterp = 9,    // Normal state restored, running debug interpreter
    155 } SelfVerificationState;
    156 #endif
    157 
    158 typedef enum JitHint {
    159    kJitHintNone = 0,
    160    kJitHintTaken = 1,         // Last inst in run was taken branch
    161    kJitHintNotTaken = 2,      // Last inst in run was not taken branch
    162    kJitHintNoBias = 3,        // Last inst in run was unbiased branch
    163 } jitHint;
    164 
    165 /*
    166  * Element of a Jit trace description. If the isCode bit is set, it describes
    167  * a contiguous sequence of Dalvik byte codes.
    168  */
    169 typedef struct {
    170     unsigned isCode:1;       // If set denotes code fragments
    171     unsigned numInsts:8;     // Number of Byte codes in run
    172     unsigned runEnd:1;       // Run ends with last byte code
    173     jitHint  hint:6;         // Hint to apply to final code of run
    174     u2    startOffset;       // Starting offset for trace run
    175 } JitCodeDesc;
    176 
    177 /*
    178  * A complete list of trace runs passed to the compiler looks like the
    179  * following:
    180  *   frag1
    181  *   frag2
    182  *   frag3
    183  *   meta1
    184  *   meta2
    185  *   frag4
    186  *
    187  * frags 1-4 have the "isCode" field set, and metas 1-2 are plain pointers or
    188  * pointers to auxiliary data structures as long as the LSB is null.
    189  * The meaning of the meta content is loosely defined. It is usually the code
    190  * fragment right before the first meta field (frag3 in this case) to
    191  * understand and parse them. Frag4 could be a dummy one with 0 "numInsts" but
    192  * the "runEnd" field set.
    193  *
    194  * For example, if a trace run contains a method inlining target, the class
    195  * type of "this" and the currently resolved method pointer are two instances
    196  * of meta information stored there.
    197  */
    198 typedef union {
    199     JitCodeDesc frag;
    200     void*       meta;
    201 } JitTraceRun;
    202 
    203 /*
    204  * Trace description as will appear in the translation cache.  Note
    205  * flexible array at end, as these will be of variable size.  To
    206  * conserve space in the translation cache, total length of JitTraceRun
    207  * array must be recomputed via seqential scan if needed.
    208  */
    209 typedef struct {
    210     const Method* method;
    211     JitTraceRun trace[0];       // Variable-length trace descriptors
    212 } JitTraceDescription;
    213 
    214 typedef enum JitMethodAttributes {
    215     kIsCallee = 0,      /* Code is part of a callee (invoked by a hot trace) */
    216     kIsHot,             /* Code is part of a hot trace */
    217     kIsLeaf,            /* Method is leaf */
    218     kIsEmpty,           /* Method is empty */
    219     kIsThrowFree,       /* Method doesn't throw */
    220     kIsGetter,          /* Method fits the getter pattern */
    221     kIsSetter,          /* Method fits the setter pattern */
    222 } JitMethodAttributes;
    223 
    224 #define METHOD_IS_CALLEE        (1 << kIsCallee)
    225 #define METHOD_IS_HOT           (1 << kIsHot)
    226 #define METHOD_IS_LEAF          (1 << kIsLeaf)
    227 #define METHOD_IS_EMPTY         (1 << kIsEmpty)
    228 #define METHOD_IS_THROW_FREE    (1 << kIsThrowFree)
    229 #define METHOD_IS_GETTER        (1 << kIsGetter)
    230 #define METHOD_IS_SETTER        (1 << kIsSetter)
    231 
    232 /* Vectors to provide optimization hints */
    233 typedef enum JitOptimizationHints {
    234     kJitOptNoLoop = 0,          // Disable loop formation/optimization
    235 } JitOptimizationHints;
    236 
    237 #define JIT_OPT_NO_LOOP         (1 << kJitOptNoLoop)
    238 
    239 typedef struct CompilerMethodStats {
    240     const Method *method;       // Used as hash entry signature
    241     int dalvikSize;             // # of bytes for dalvik bytecodes
    242     int compiledDalvikSize;     // # of compiled dalvik bytecodes
    243     int nativeSize;             // # of bytes for produced native code
    244     int attributes;             // attribute vector
    245 } CompilerMethodStats;
    246 
    247 struct CompilationUnit;
    248 struct BasicBlock;
    249 struct SSARepresentation;
    250 struct GrowableList;
    251 struct JitEntry;
    252 struct MIR;
    253 
    254 bool dvmCompilerSetupCodeCache(void);
    255 bool dvmCompilerArchInit(void);
    256 void dvmCompilerArchDump(void);
    257 bool dvmCompilerStartup(void);
    258 void dvmCompilerShutdown(void);
    259 bool dvmCompilerWorkEnqueue(const u2* pc, WorkOrderKind kind, void* info);
    260 void *dvmCheckCodeCache(void *method);
    261 CompilerMethodStats *dvmCompilerAnalyzeMethodBody(const Method *method,
    262                                                   bool isCallee);
    263 bool dvmCompilerCanIncludeThisInstruction(const Method *method,
    264                                           const DecodedInstruction *insn);
    265 bool dvmCompileMethod(struct CompilationUnit *cUnit, const Method *method,
    266                       JitTranslationInfo *info);
    267 bool dvmCompileTrace(JitTraceDescription *trace, int numMaxInsts,
    268                      JitTranslationInfo *info, jmp_buf *bailPtr, int optHints);
    269 void dvmCompilerDumpStats(void);
    270 void dvmCompilerDrainQueue(void);
    271 void dvmJitUnchainAll(void);
    272 void dvmCompilerSortAndPrintTraceProfiles(void);
    273 void dvmCompilerPerformSafePointChecks(void);
    274 void dvmCompilerInlineMIR(struct CompilationUnit *cUnit);
    275 void dvmInitializeSSAConversion(struct CompilationUnit *cUnit);
    276 int dvmConvertSSARegToDalvik(struct CompilationUnit *cUnit, int ssaReg);
    277 bool dvmCompilerLoopOpt(struct CompilationUnit *cUnit);
    278 void dvmCompilerNonLoopAnalysis(struct CompilationUnit *cUnit);
    279 void dvmCompilerFindLiveIn(struct CompilationUnit *cUnit,
    280                            struct BasicBlock *bb);
    281 void dvmCompilerDoSSAConversion(struct CompilationUnit *cUnit,
    282                                 struct BasicBlock *bb);
    283 void dvmCompilerDoConstantPropagation(struct CompilationUnit *cUnit,
    284                                       struct BasicBlock *bb);
    285 void dvmCompilerFindInductionVariables(struct CompilationUnit *cUnit,
    286                                        struct BasicBlock *bb);
    287 char *dvmCompilerGetDalvikDisassembly(DecodedInstruction *insn, char *note);
    288 char *dvmCompilerGetSSAString(struct CompilationUnit *cUnit,
    289                               struct SSARepresentation *ssaRep);
    290 void dvmCompilerDataFlowAnalysisDispatcher(struct CompilationUnit *cUnit,
    291                 void (*func)(struct CompilationUnit *, struct BasicBlock *));
    292 void dvmCompilerStateRefresh(void);
    293 JitTraceDescription *dvmCopyTraceDescriptor(const u2 *pc,
    294                                             const struct JitEntry *desc);
    295 void *dvmCompilerGetInterpretTemplate();
    296 #endif /* _DALVIK_VM_COMPILER */
    297