/* * Copyright (C) 2009 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * Jit control */ #ifndef DALVIK_INTERP_JIT_H_ #define DALVIK_INTERP_JIT_H_ #include "InterpDefs.h" #include "mterp/common/jit-config.h" #define JIT_MAX_TRACE_LEN 100 #if defined (WITH_SELF_VERIFICATION) #define REG_SPACE 256 /* default size of shadow space */ #define HEAP_SPACE JIT_MAX_TRACE_LEN /* default size of heap space */ struct ShadowHeap { int addr; int data; }; struct InstructionTrace { int addr; DecodedInstruction decInsn; }; struct ShadowSpace { const u2* startPC; /* starting pc of jitted region */ u4* fp; /* starting fp of jitted region */ const Method *method; DvmDex* methodClassDex; JValue retval; const u1* interpStackEnd; SelfVerificationState jitExitState; /* exit point for JIT'ed code */ SelfVerificationState selfVerificationState; /* current SV running state */ const u2* endPC; /* ending pc of jitted region */ void* shadowFP; /* pointer to fp in shadow space */ int* registerSpace; /* copy of register state */ int registerSpaceSize; /* current size of register space */ ShadowHeap heapSpace[HEAP_SPACE]; /* copy of heap space */ ShadowHeap* heapSpaceTail; /* tail pointer to heapSpace */ const void* endShadowFP; /* ending fp in shadow space */ InstructionTrace trace[JIT_MAX_TRACE_LEN]; /* opcode trace for debugging */ int traceLength; /* counter for current trace length */ }; /* * Self verification functions. */ extern "C" { void* dvmSelfVerificationShadowSpaceAlloc(Thread* self); void dvmSelfVerificationShadowSpaceFree(Thread* self); void* dvmSelfVerificationSaveState(const u2* pc, u4* fp, Thread* self, int targetTrace); void* dvmSelfVerificationRestoreState(const u2* pc, u4* fp, SelfVerificationState exitPoint, Thread *self); void dvmCheckSelfVerification(const u2* pc, Thread* self); } #endif /* * Offsets for metadata in the trace run array from the trace that ends with * invoke instructions. */ #define JIT_TRACE_CLASS_DESC 1 #define JIT_TRACE_CLASS_LOADER 2 #define JIT_TRACE_CUR_METHOD 3 /* * JitTable hash function. */ static inline u4 dvmJitHashMask( const u2* p, u4 mask ) { return ((((u4)p>>12)^(u4)p)>>1) & (mask); } static inline u4 dvmJitHash( const u2* p ) { return dvmJitHashMask( p, gDvmJit.jitTableMask ); } /* * The width of the chain field in JitEntryInfo sets the upper * bound on the number of translations. Be careful if changing * the size of JitEntry struct - the Dalvik PC to JitEntry * hash functions have built-in knowledge of the size. */ #define JIT_ENTRY_CHAIN_WIDTH 2 #define JIT_MAX_ENTRIES (1 << (JIT_ENTRY_CHAIN_WIDTH * 8)) /* * The trace profiling counters are allocated in blocks and individual * counters must not move so long as any referencing trace exists. */ #define JIT_PROF_BLOCK_ENTRIES 1024 #define JIT_PROF_BLOCK_BUCKETS (JIT_MAX_ENTRIES / JIT_PROF_BLOCK_ENTRIES) typedef s4 JitTraceCounter_t; struct JitTraceProfCounters { unsigned int next; JitTraceCounter_t *buckets[JIT_PROF_BLOCK_BUCKETS]; }; /* * Entries in the JIT's address lookup hash table. * Fields which may be updated by multiple threads packed into a * single 32-bit word to allow use of atomic update. */ struct JitEntryInfo { unsigned int isMethodEntry:1; unsigned int inlineCandidate:1; unsigned int profileEnabled:1; JitInstructionSetType instructionSet:3; unsigned int profileOffset:5; unsigned int unused:5; u2 chain; /* Index of next in chain */ }; union JitEntryInfoUnion { JitEntryInfo info; volatile int infoWord; }; struct JitEntry { JitEntryInfoUnion u; const u2* dPC; /* Dalvik code address */ void* codeAddress; /* Code address of native translation */ }; extern "C" { void dvmCheckJit(const u2* pc, Thread* self); void* dvmJitGetTraceAddr(const u2* dPC); void* dvmJitGetMethodAddr(const u2* dPC); void* dvmJitGetTraceAddrThread(const u2* dPC, Thread* self); void* dvmJitGetMethodAddrThread(const u2* dPC, Thread* self); void dvmJitCheckTraceRequest(Thread* self); void dvmJitStopTranslationRequests(void); #if defined(WITH_JIT_TUNING) void dvmBumpNoChain(int from); void dvmBumpNormal(void); void dvmBumpPunt(int from); #endif void dvmJitStats(void); bool dvmJitResizeJitTable(unsigned int size); void dvmJitResetTable(void); JitEntry *dvmJitFindEntry(const u2* pc, bool isMethodEntry); s8 dvmJitd2l(double d); s8 dvmJitf2l(float f); void dvmJitSetCodeAddr(const u2* dPC, void *nPC, JitInstructionSetType set, bool isMethodEntry, int profilePrefixSize); void dvmJitEndTraceSelect(Thread* self, const u2* dPC); JitTraceCounter_t *dvmJitNextTraceCounter(void); void dvmJitTraceProfilingOff(void); void dvmJitTraceProfilingOn(void); void dvmJitChangeProfileMode(TraceProfilingModes newState); void dvmJitDumpTraceDesc(JitTraceDescription *trace); void dvmJitUpdateThreadStateSingle(Thread* threead); void dvmJitUpdateThreadStateAll(void); void dvmJitResumeTranslation(Thread* self, const u2* pc, const u4* fp); } #endif // DALVIK_INTERP_JIT_H_