1 /* 2 * Copyright (C) 2008 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 /* 18 * Android's method call profiling goodies. 19 */ 20 #ifndef _DALVIK_PROFILE 21 #define _DALVIK_PROFILE 22 23 #ifndef NOT_VM /* for utilities that sneakily include this file */ 24 25 #include <stdio.h> 26 27 /* External allocations are hackish enough that it's worthwhile 28 * separating them for possible removal later. 29 */ 30 #define PROFILE_EXTERNAL_ALLOCATIONS 1 31 32 struct Thread; // extern 33 34 35 /* boot init */ 36 bool dvmProfilingStartup(void); 37 void dvmProfilingShutdown(void); 38 39 /* 40 * Method trace state. This is currently global. In theory we could make 41 * most of this per-thread. 42 * 43 */ 44 typedef struct MethodTraceState { 45 /* these are set during VM init */ 46 Method* gcMethod; 47 Method* classPrepMethod; 48 49 /* active state */ 50 pthread_mutex_t startStopLock; 51 pthread_cond_t threadExitCond; 52 FILE* traceFile; 53 int bufferSize; 54 int flags; 55 56 bool traceEnabled; 57 u1* buf; 58 volatile int curOffset; 59 u8 startWhen; 60 int overflow; 61 } MethodTraceState; 62 63 /* 64 * Memory allocation profiler state. This is used both globally and 65 * per-thread. 66 * 67 * If you add a field here, zero it out in dvmStartAllocCounting(). 68 */ 69 typedef struct AllocProfState { 70 bool enabled; // is allocation tracking enabled? 71 72 int allocCount; // #of objects allocated 73 int allocSize; // cumulative size of objects 74 75 int failedAllocCount; // #of times an allocation failed 76 int failedAllocSize; // cumulative size of failed allocations 77 78 int freeCount; // #of objects freed 79 int freeSize; // cumulative size of freed objects 80 81 int gcCount; // #of times an allocation triggered a GC 82 83 #if PROFILE_EXTERNAL_ALLOCATIONS 84 int externalAllocCount; // #of calls to dvmTrackExternalAllocation() 85 int externalAllocSize; // #of bytes passed to ...ExternalAllocation() 86 87 int failedExternalAllocCount; // #of times an allocation failed 88 int failedExternalAllocSize; // cumulative size of failed allocations 89 90 int externalFreeCount; // #of calls to dvmTrackExternalFree() 91 int externalFreeSize; // #of bytes passed to ...ExternalFree() 92 #endif // PROFILE_EXTERNAL_ALLOCATIONS 93 } AllocProfState; 94 95 96 /* 97 * Start/stop method tracing. 98 */ 99 void dvmMethodTraceStart(const char* traceFileName, int traceFd, int bufferSize, 100 int flags); 101 bool dvmIsMethodTraceActive(void); 102 void dvmMethodTraceStop(void); 103 104 /* 105 * Start/stop emulator tracing. 106 */ 107 void dvmEmulatorTraceStart(void); 108 void dvmEmulatorTraceStop(void); 109 110 /* 111 * Start/stop Dalvik instruction counting. 112 */ 113 void dvmStartInstructionCounting(); 114 void dvmStopInstructionCounting(); 115 116 /* 117 * Bit flags for dvmMethodTraceStart "flags" argument. These must match 118 * the values in android.os.Debug. 119 */ 120 enum { 121 TRACE_ALLOC_COUNTS = 0x01, 122 }; 123 124 /* 125 * Call these when a method enters or exits. 126 */ 127 #ifdef WITH_PROFILER 128 # define TRACE_METHOD_ENTER(_self, _method) \ 129 do { \ 130 if (gDvm.activeProfilers != 0) { \ 131 if (gDvm.methodTrace.traceEnabled) \ 132 dvmMethodTraceAdd(_self, _method, METHOD_TRACE_ENTER); \ 133 if (gDvm.emulatorTraceEnableCount != 0) \ 134 dvmEmitEmulatorTrace(_method, METHOD_TRACE_ENTER); \ 135 } \ 136 } while(0); 137 # define TRACE_METHOD_EXIT(_self, _method) \ 138 do { \ 139 if (gDvm.activeProfilers != 0) { \ 140 if (gDvm.methodTrace.traceEnabled) \ 141 dvmMethodTraceAdd(_self, _method, METHOD_TRACE_EXIT); \ 142 if (gDvm.emulatorTraceEnableCount != 0) \ 143 dvmEmitEmulatorTrace(_method, METHOD_TRACE_EXIT); \ 144 } \ 145 } while(0); 146 # define TRACE_METHOD_UNROLL(_self, _method) \ 147 do { \ 148 if (gDvm.activeProfilers != 0) { \ 149 if (gDvm.methodTrace.traceEnabled) \ 150 dvmMethodTraceAdd(_self, _method, METHOD_TRACE_UNROLL); \ 151 if (gDvm.emulatorTraceEnableCount != 0) \ 152 dvmEmitEmulatorTrace(_method, METHOD_TRACE_UNROLL); \ 153 } \ 154 } while(0); 155 #else 156 # define TRACE_METHOD_ENTER(_self, _method) ((void) 0) 157 # define TRACE_METHOD_EXIT(_self, _method) ((void) 0) 158 # define TRACE_METHOD_UNROLL(_self, _method) ((void) 0) 159 #endif 160 161 void dvmMethodTraceAdd(struct Thread* self, const Method* method, int action); 162 void dvmEmitEmulatorTrace(const Method* method, int action); 163 164 void dvmMethodTraceGCBegin(void); 165 void dvmMethodTraceGCEnd(void); 166 void dvmMethodTraceClassPrepBegin(void); 167 void dvmMethodTraceClassPrepEnd(void); 168 169 /* 170 * Start/stop alloc counting. 171 */ 172 void dvmStartAllocCounting(void); 173 void dvmStopAllocCounting(void); 174 175 #endif 176 177 178 /* 179 * Enumeration for the two "action" bits. 180 */ 181 enum { 182 METHOD_TRACE_ENTER = 0x00, // method entry 183 METHOD_TRACE_EXIT = 0x01, // method exit 184 METHOD_TRACE_UNROLL = 0x02, // method exited by exception unrolling 185 // 0x03 currently unused 186 }; 187 188 #define TOKEN_CHAR '*' 189 #define TRACE_VERSION 1 190 191 /* 192 * Common definitions, shared with the dump tool. 193 */ 194 #define METHOD_ACTION_MASK 0x03 /* two bits */ 195 #define METHOD_ID(_method) ((_method) & (~METHOD_ACTION_MASK)) 196 #define METHOD_ACTION(_method) (((unsigned int)(_method)) & METHOD_ACTION_MASK) 197 #define METHOD_COMBINE(_method, _action) ((_method) | (_action)) 198 199 #endif /*_DALVIK_PROFILE*/ 200