/*
* 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_