00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064 #include "hprof.h"
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077 #define BEGIN_TRACKER_CALLBACK() \
00078 { \
00079 jboolean bypass = JNI_TRUE; \
00080 rawMonitorEnter(gdata->callbackLock); { \
00081 if ( gdata->tracking_engaged != 0 ) { \
00082 if (!gdata->vm_death_callback_active) { \
00083 gdata->active_callbacks++; \
00084 bypass = JNI_FALSE; \
00085 } \
00086 } \
00087 } rawMonitorExit(gdata->callbackLock); \
00088 if ( !bypass ) { \
00089
00090
00091 #define END_TRACKER_CALLBACK() \
00092 rawMonitorEnter(gdata->callbackLock); { \
00093 gdata->active_callbacks--; \
00094 if (gdata->active_callbacks < 0) { \
00095 HPROF_ERROR(JNI_TRUE, "Problems tracking callbacks"); \
00096 } \
00097 if (gdata->vm_death_callback_active) { \
00098 if (gdata->active_callbacks == 0) { \
00099 rawMonitorNotifyAll(gdata->callbackLock); \
00100 } \
00101 } \
00102 } rawMonitorExit(gdata->callbackLock); \
00103 } \
00104 }
00105
00106
00107
00108
00109
00110
00111
00112 static void JNICALL
00113 Tracker_nativeNewArray
00114 (JNIEnv *env, jclass clazz, jobject thread, jobject obj)
00115 {
00116 BEGIN_TRACKER_CALLBACK() {
00117 event_newarray(env, thread, obj);
00118 } END_TRACKER_CALLBACK();
00119 }
00120
00121
00122
00123
00124
00125
00126 static void JNICALL
00127 Tracker_nativeObjectInit
00128 (JNIEnv *env, jclass clazz, jobject thread, jobject obj)
00129 {
00130 BEGIN_TRACKER_CALLBACK() {
00131 event_object_init(env, thread, obj);
00132 } END_TRACKER_CALLBACK();
00133 }
00134
00135
00136
00137
00138
00139
00140 static void JNICALL
00141 Tracker_nativeCallSite
00142 (JNIEnv *env, jclass clazz, jobject thread, jint cnum, jint mnum)
00143 {
00144 BEGIN_TRACKER_CALLBACK() {
00145 event_call(env, thread, cnum, mnum);
00146 } END_TRACKER_CALLBACK();
00147 }
00148
00149
00150
00151
00152
00153
00154 static void JNICALL
00155 Tracker_nativeReturnSite
00156 (JNIEnv *env, jclass clazz, jobject thread, jint cnum, jint mnum)
00157 {
00158 BEGIN_TRACKER_CALLBACK() {
00159 event_return(env, thread, cnum, mnum);
00160 } END_TRACKER_CALLBACK();
00161 }
00162
00163
00164
00165
00166
00167 static void
00168 set_engaged(JNIEnv *env, jint engaged)
00169 {
00170 LOG3("set_engaged()", "engaging tracking", engaged);
00171
00172 if ( ! gdata->bci ) {
00173 return;
00174 }
00175 rawMonitorEnter(gdata->callbackLock); {
00176 if ( gdata->tracking_engaged != engaged ) {
00177 jfieldID field;
00178 jclass tracker_class;
00179
00180 tracker_class = class_get_class(env, gdata->tracker_cnum);
00181 gdata->tracking_engaged = 0;
00182
00183 HPROF_ASSERT(tracker_class!=NULL);
00184 exceptionClear(env);
00185 field = getStaticFieldID(env, tracker_class,
00186 TRACKER_ENGAGED_NAME, TRACKER_ENGAGED_SIG);
00187 setStaticIntField(env, tracker_class, field, engaged);
00188 exceptionClear(env);
00189
00190 LOG3("set_engaged()", "tracking engaged", engaged);
00191
00192 gdata->tracking_engaged = engaged;
00193 }
00194 } rawMonitorExit(gdata->callbackLock);
00195 }
00196
00197 void
00198 tracker_engage(JNIEnv *env)
00199 {
00200 set_engaged(env, 0xFFFF);
00201 }
00202
00203 void
00204 tracker_disengage(JNIEnv *env)
00205 {
00206 set_engaged(env, 0);
00207 }
00208
00209 jboolean
00210 tracker_method(jmethodID method)
00211 {
00212 int i;
00213
00214 if ( ! gdata->bci ) {
00215 return JNI_FALSE;
00216 }
00217
00218 HPROF_ASSERT(method!=NULL);
00219 HPROF_ASSERT(gdata->tracker_method_count > 0);
00220 for ( i = 0 ; i < gdata->tracker_method_count ; i++ ) {
00221 HPROF_ASSERT(gdata->tracker_methods[i].method!=NULL);
00222 if ( method == gdata->tracker_methods[i].method ) {
00223 return JNI_TRUE;
00224 }
00225 }
00226 return JNI_FALSE;
00227 }
00228
00229 static JNINativeMethod registry[4] =
00230 {
00231 { TRACKER_NEWARRAY_NATIVE_NAME, TRACKER_NEWARRAY_NATIVE_SIG,
00232 (void*)&Tracker_nativeNewArray },
00233 { TRACKER_OBJECT_INIT_NATIVE_NAME, TRACKER_OBJECT_INIT_NATIVE_SIG,
00234 (void*)&Tracker_nativeObjectInit },
00235 { TRACKER_CALL_NATIVE_NAME, TRACKER_CALL_NATIVE_SIG,
00236 (void*)&Tracker_nativeCallSite },
00237 { TRACKER_RETURN_NATIVE_NAME, TRACKER_RETURN_NATIVE_SIG,
00238 (void*)&Tracker_nativeReturnSite }
00239 };
00240
00241 static struct {
00242 char *name;
00243 char *sig;
00244 } tracker_methods[] =
00245 {
00246 { TRACKER_NEWARRAY_NAME, TRACKER_NEWARRAY_SIG },
00247 { TRACKER_OBJECT_INIT_NAME, TRACKER_OBJECT_INIT_SIG },
00248 { TRACKER_CALL_NAME, TRACKER_CALL_SIG },
00249 { TRACKER_RETURN_NAME, TRACKER_RETURN_SIG },
00250 { TRACKER_NEWARRAY_NATIVE_NAME, TRACKER_NEWARRAY_NATIVE_SIG },
00251 { TRACKER_OBJECT_INIT_NATIVE_NAME, TRACKER_OBJECT_INIT_NATIVE_SIG },
00252 { TRACKER_CALL_NATIVE_NAME, TRACKER_CALL_NATIVE_SIG },
00253 { TRACKER_RETURN_NATIVE_NAME, TRACKER_RETURN_NATIVE_SIG }
00254 };
00255
00256 void
00257 tracker_setup_class(void)
00258 {
00259 ClassIndex cnum;
00260 LoaderIndex loader_index;
00261
00262 HPROF_ASSERT(gdata->tracker_cnum==0);
00263 loader_index = loader_find_or_create(NULL,NULL);
00264 cnum = class_find_or_create(TRACKER_CLASS_SIG, loader_index);
00265 gdata->tracker_cnum = cnum;
00266 HPROF_ASSERT(cnum!=0);
00267 class_add_status(cnum, CLASS_SPECIAL);
00268 }
00269
00270 void
00271 tracker_setup_methods(JNIEnv *env)
00272 {
00273 ClassIndex cnum;
00274 LoaderIndex loader_index;
00275 int i;
00276 jclass object_class;
00277 jclass tracker_class;
00278
00279 if ( ! gdata->bci ) {
00280 return;
00281 }
00282
00283 loader_index = loader_find_or_create(NULL,NULL);
00284 cnum = class_find_or_create(OBJECT_CLASS_SIG, loader_index);
00285 object_class = class_get_class(env, cnum);
00286 tracker_class = class_get_class(env, gdata->tracker_cnum);
00287
00288 CHECK_EXCEPTIONS(env) {
00289 registerNatives(env, tracker_class, registry,
00290 (int)sizeof(registry)/(int)sizeof(registry[0]));
00291 } END_CHECK_EXCEPTIONS;
00292
00293 HPROF_ASSERT(tracker_class!=NULL);
00294
00295 gdata->tracker_method_count =
00296 (int)sizeof(tracker_methods)/(int)sizeof(tracker_methods[0]);
00297
00298 HPROF_ASSERT(gdata->tracker_method_count <=
00299 (int)(sizeof(gdata->tracker_methods)/sizeof(gdata->tracker_methods[0])));
00300
00301 CHECK_EXCEPTIONS(env) {
00302 gdata->object_init_method = getMethodID(env, object_class,
00303 OBJECT_INIT_NAME, OBJECT_INIT_SIG);
00304 for ( i=0 ; i < gdata->tracker_method_count ; i++ ) {
00305 gdata->tracker_methods[i].name =
00306 string_find_or_create(tracker_methods[i].name);
00307 gdata->tracker_methods[i].sig =
00308 string_find_or_create(tracker_methods[i].sig);
00309 gdata->tracker_methods[i].method =
00310 getStaticMethodID(env, tracker_class,
00311 tracker_methods[i].name, tracker_methods[i].sig);
00312 HPROF_ASSERT(gdata->tracker_methods[i].method!=NULL);
00313 LOG2("tracker_setup_methods(): Found", tracker_methods[i].name);
00314 }
00315 } END_CHECK_EXCEPTIONS;
00316 }