| /* |
| * Copyright (C) 2008 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. |
| */ |
| /* |
| * Dalvik interpreter definitions. These are internal to the interpreter. |
| * |
| * This includes defines, types, function declarations, and inline functions |
| * that are common to all interpreter implementations. |
| * |
| * Functions and globals declared here are defined in Interp.c. |
| */ |
| #ifndef _DALVIK_INTERP_DEFS |
| #define _DALVIK_INTERP_DEFS |
| |
| |
| /* |
| * Specify the starting point when switching between interpreters. |
| */ |
| typedef enum InterpEntry { |
| kInterpEntryInstr = 0, // continue to next instruction |
| kInterpEntryReturn = 1, // jump to method return |
| kInterpEntryThrow = 2, // jump to exception throw |
| #if defined(WITH_JIT) |
| kInterpEntryResume = 3, // Resume after single-step |
| #endif |
| } InterpEntry; |
| |
| #if defined(WITH_JIT) |
| /* |
| * There are six entry points from the compiled code to the interpreter: |
| * 1) dvmJitToInterpNormal: find if there is a corresponding compilation for |
| * the new dalvik PC. If so, chain the originating compilation with the |
| * target then jump to it. |
| * 2) dvmJitToInterpInvokeNoChain: similar to 1) but don't chain. This is |
| * for handling 1-to-many mappings like virtual method call and |
| * packed switch. |
| * 3) dvmJitToInterpPunt: use the fast interpreter to execute the next |
| * instruction(s) and stay there as long as it is appropriate to return |
| * to the compiled land. This is used when the jit'ed code is about to |
| * throw an exception. |
| * 4) dvmJitToInterpSingleStep: use the portable interpreter to execute the |
| * next instruction only and return to pre-specified location in the |
| * compiled code to resume execution. This is mainly used as debugging |
| * feature to bypass problematic opcode implementations without |
| * disturbing the trace formation. |
| * 5) dvmJitToTraceSelect: if there is a single exit from a translation that |
| * has already gone hot enough to be translated, we should assume that |
| * the exit point should also be translated (this is a common case for |
| * invokes). This trace exit will first check for a chaining |
| * opportunity, and if none is available will switch to the debug |
| * interpreter immediately for trace selection (as if threshold had |
| * just been reached). |
| * 6) dvmJitToPredictedChain: patch the chaining cell for a virtual call site |
| * to a predicted callee. |
| */ |
| struct JitToInterpEntries { |
| void *dvmJitToInterpNormal; |
| void *dvmJitToInterpNoChain; |
| void *dvmJitToInterpPunt; |
| void *dvmJitToInterpSingleStep; |
| void *dvmJitToTraceSelect; |
| void *dvmJitToPatchPredictedChain; |
| }; |
| |
| #define JIT_TRACE_THRESH_FILTER_SIZE 16 |
| #endif |
| |
| /* |
| * Interpreter context, used when switching from one interpreter to |
| * another. We also tuck "mterp" state in here. |
| */ |
| typedef struct InterpState { |
| /* |
| * To make some mterp state updates easier, "pc" and "fp" MUST come |
| * first and MUST appear in this order. |
| */ |
| const u2* pc; // program counter |
| u4* fp; // frame pointer |
| |
| JValue retval; // return value -- "out" only |
| const Method* method; // method being executed |
| |
| |
| /* ---------------------------------------------------------------------- |
| * Mterp-only state |
| */ |
| DvmDex* methodClassDex; |
| Thread* self; |
| |
| /* housekeeping */ |
| void* bailPtr; |
| |
| /* |
| * These are available globally, from gDvm, or from another glue field |
| * (self/method). They're copied in here for speed. |
| */ |
| const u1* interpStackEnd; |
| volatile int* pSelfSuspendCount; |
| #if defined(WITH_DEBUGGER) |
| volatile u1* pDebuggerActive; |
| #endif |
| #if defined(WITH_PROFILER) |
| volatile int* pActiveProfilers; |
| #endif |
| /* ---------------------------------------------------------------------- |
| */ |
| |
| /* |
| * Interpreter switching. |
| */ |
| InterpEntry entryPoint; // what to do when we start |
| int nextMode; // INTERP_STD, INTERP_DBG |
| |
| #if defined(WITH_JIT) |
| /* |
| * Local copies of field from gDvm placed here for fast access |
| */ |
| unsigned char* pJitProfTable; |
| JitState jitState; |
| void* jitResume; |
| u2* jitResumePC; |
| #endif |
| |
| #if defined(WITH_PROFILER) || defined(WITH_DEBUGGER) |
| bool debugIsMethodEntry; // used for method entry event triggers |
| #endif |
| #if defined(WITH_TRACKREF_CHECKS) |
| int debugTrackedRefStart; // tracked refs from prior invocations |
| #endif |
| |
| #if defined(WITH_JIT) |
| struct JitToInterpEntries jitToInterpEntries; |
| |
| int currTraceRun; |
| int totalTraceLen; // Number of Dalvik insts in trace |
| const u2* currTraceHead; // Start of the trace we're building |
| const u2* currRunHead; // Start of run we're building |
| int currRunLen; // Length of run in 16-bit words |
| int lastThreshFilter; |
| const u2* threshFilter[JIT_TRACE_THRESH_FILTER_SIZE]; |
| JitTraceRun trace[MAX_JIT_RUN_LEN]; |
| #endif |
| |
| } InterpState; |
| |
| /* |
| * These are generated from InterpCore.h. |
| */ |
| extern bool dvmInterpretDbg(Thread* self, InterpState* interpState); |
| extern bool dvmInterpretStd(Thread* self, InterpState* interpState); |
| #define INTERP_STD 0 |
| #define INTERP_DBG 1 |
| |
| /* |
| * "mterp" interpreter. |
| */ |
| extern bool dvmMterpStd(Thread* self, InterpState* interpState); |
| |
| /* |
| * Get the "this" pointer from the current frame. |
| */ |
| Object* dvmGetThisPtr(const Method* method, const u4* fp); |
| |
| /* |
| * Verify that our tracked local references are valid. |
| */ |
| void dvmInterpCheckTrackedRefs(Thread* self, const Method* method, |
| int debugTrackedRefStart); |
| |
| /* |
| * Process switch statement. |
| */ |
| s4 dvmInterpHandlePackedSwitch(const u2* switchData, s4 testVal); |
| s4 dvmInterpHandleSparseSwitch(const u2* switchData, s4 testVal); |
| |
| /* |
| * Process fill-array-data. |
| */ |
| bool dvmInterpHandleFillArrayData(ArrayObject* arrayObject, |
| const u2* arrayData); |
| |
| /* |
| * Find an interface method. |
| */ |
| Method* dvmInterpFindInterfaceMethod(ClassObject* thisClass, u4 methodIdx, |
| const Method* method, DvmDex* methodClassDex); |
| |
| /* |
| * Determine if the debugger or profiler is currently active. Used when |
| * selecting which interpreter to start or switch to. |
| */ |
| static inline bool dvmDebuggerOrProfilerActive(void) |
| { |
| return gDvm.debuggerActive |
| #if defined(WITH_PROFILER) |
| || gDvm.activeProfilers != 0 |
| #endif |
| ; |
| } |
| |
| #if defined(WITH_JIT) |
| /* |
| * Determine if the jit, debugger or profiler is currently active. Used when |
| * selecting which interpreter to switch to. |
| */ |
| static inline bool dvmJitDebuggerOrProfilerActive(int jitState) |
| { |
| return jitState != kJitOff |
| #if defined(WITH_PROFILER) |
| || gDvm.activeProfilers != 0 |
| #endif |
| ||gDvm.debuggerActive; |
| } |
| #endif |
| |
| #endif /*_DALVIK_INTERP_DEFS*/ |