00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 # include "incls/_precompiled.incl"
00025 # include "incls/_fprofiler.cpp.incl"
00026
00027 pnode** FlatProfiler::table = NULL;
00028 int FlatProfiler::table_size = 1024;
00029
00030 DeltaProcess* FlatProfiler::proc = NULL;
00031 FlatProfilerTask* FlatProfiler::task = NULL;
00032 timer FlatProfiler::time;
00033
00034 int FlatProfiler::gc_ticks = 0;
00035 int FlatProfiler::semaphore_ticks = 0;
00036 int FlatProfiler::stub_ticks = 0;
00037 int FlatProfiler::unknown_ticks = 0;
00038 int FlatProfiler::compiler_ticks = 0;
00039
00040 static const int col2 = 11;
00041 static const int col3 = 30;
00042 static const int col4 = 55;
00043
00044 class tick_counter {
00045 public:
00046 int ticks_in_code;
00047 int ticks_in_primitives;
00048 int ticks_in_compiler;
00049 int ticks_in_pics;
00050 int ticks_in_other;
00051
00052 tick_counter() {
00053 ticks_in_code = 0;
00054 ticks_in_primitives = 0;
00055 ticks_in_compiler = 0;
00056 ticks_in_pics = 0;
00057 ticks_in_other = 0;
00058 }
00059
00060
00061 int total() const {
00062 return ticks_in_code
00063 + ticks_in_primitives
00064 + ticks_in_compiler
00065 + ticks_in_pics
00066 + ticks_in_other;
00067 }
00068
00069 void add(tick_counter* a) {
00070 ticks_in_code += a->ticks_in_code;
00071 ticks_in_primitives += a->ticks_in_primitives;
00072 ticks_in_compiler += a->ticks_in_compiler;
00073 ticks_in_pics += a->ticks_in_pics;
00074 ticks_in_other += a->ticks_in_other;
00075 }
00076
00077 void update(TickPosition where) {
00078 switch(where) {
00079 case in_code: ticks_in_code++; break;
00080 case in_primitive: ticks_in_primitives++; break;
00081 case in_compiler: ticks_in_compiler++; break;
00082 case in_pic: ticks_in_pics++; break;
00083 case other: ticks_in_other++; break;
00084 }
00085 }
00086
00087 void print_code(outputStream* st, int total_ticks) {
00088 st->print("%5.1f%% %3d ", total() * 100.0 / total_ticks, ticks_in_code);
00089 }
00090
00091 void print_other(outputStream* st) {
00092 if (ticks_in_primitives > 0) st->print("prim=%d ", ticks_in_primitives);
00093 if (ticks_in_compiler > 0) st->print("comp=%d ", ticks_in_compiler);
00094 if (ticks_in_pics > 0) st->print("pics=%d ", ticks_in_pics);
00095 if (ticks_in_other > 0) st->print("other=%d ", ticks_in_other);
00096 }
00097 };
00098
00099 class pnode : public CHeapObj {
00100 private:
00101 pnode* _next;
00102 public:
00103 tick_counter ticks;
00104
00105 public:
00106 pnode() {
00107 _next = NULL;
00108 }
00109
00110 ~pnode() {
00111 if (_next)
00112 delete _next;
00113 }
00114
00115 void set_next(pnode* n) { _next = n; }
00116 pnode* next() { return _next; }
00117
00118 void update(TickPosition where) { ticks.update(where);}
00119 int total_ticks() { return ticks.total(); }
00120
00121 virtual bool is_interpreted() const { return false; }
00122 virtual bool is_compiled() const { return false; }
00123
00124 virtual bool match(methodOop m, klassOop k) { return false; }
00125 virtual bool match(nmethod* nm) { return false; }
00126
00127
00128 static void print_title(outputStream* st) {
00129 st->fill_to(col2);
00130 st->print("Receiver");
00131 st->fill_to(col3);
00132 st->print("Method");
00133 st->fill_to(col4);
00134 st->print_cr("Leaf ticks");
00135 }
00136
00137 static void print_total(outputStream* st, tick_counter* t, int total, char* msg) {
00138 t->print_code(st, total);
00139 st->print(msg);
00140 st->fill_to(col4);
00141 t->print_other(st);
00142 st->cr();
00143 }
00144
00145 virtual methodOop method() = 0;
00146 virtual klassOop receiver_klass() = 0;
00147
00148 void print_receiver_klass_on(outputStream* st) {
00149 receiver_klass()->klass_part()->print_name_on(st);
00150 }
00151
00152 virtual void print_method_on(outputStream* st) {
00153 methodOop m = method();
00154 if (m->is_blockMethod()) {
00155 st->print("[] ");
00156 m->enclosing_method_selector()->print_symbol_on(st);
00157 } else {
00158 m->selector()->print_symbol_on(st);
00159 }
00160
00161 if (ProfilerShowMethodHolder) {
00162 klassOop method_holder = receiver_klass()->klass_part()->lookup_method_holder_for(m);
00163 if (method_holder && (method_holder != receiver_klass())) {
00164 std->print(", in ");
00165 method_holder->klass_part()->print_name_on(std);
00166 }
00167 }
00168 }
00169
00170 virtual void print(outputStream* st, int total_ticks) {
00171 ticks.print_code(st, total_ticks);
00172 st->fill_to(col2);
00173 print_receiver_klass_on(st);
00174 st->fill_to(col3);
00175
00176 print_method_on(st);
00177 st->fill_to(col4);
00178
00179 ticks.print_other(st);
00180 st->cr();
00181 }
00182
00183
00184 static int compare(pnode** a, pnode** b) { return (*b)->total_ticks() - (*a)->total_ticks(); }
00185 };
00186
00187 class interpretedNode : public pnode {
00188 private:
00189 methodOop _method;
00190 klassOop _receiver_klass;
00191 public:
00192 interpretedNode(methodOop method, klassOop receiver_klass, TickPosition where) : pnode() {
00193 _method = method;
00194 _receiver_klass = receiver_klass;
00195 update(where);
00196 }
00197
00198 bool is_interpreted() const { return true; }
00199
00200 bool match(methodOop m, klassOop k) {
00201 return _method == m
00202 && _receiver_klass == k;
00203 }
00204
00205 methodOop method() { return _method; }
00206 klassOop receiver_klass() { return _receiver_klass; }
00207
00208 static void print_title(outputStream* st) {
00209 st->print(" Int");
00210 pnode::print_title(st);
00211 }
00212
00213 void print(outputStream* st, int total_ticks) {
00214 pnode::print(st, total_ticks);
00215 }
00216 };
00217
00218 class compiledNode : public pnode {
00219 private:
00220 nmethod* nm;
00221 public:
00222 compiledNode(nmethod* nm, TickPosition where) : pnode() {
00223 this->nm = nm;
00224 update(where);
00225 }
00226 bool is_compiled() const { return true; }
00227
00228 bool match(nmethod* m) { return nm == m; }
00229
00230 methodOop method() { return nm->method(); }
00231 klassOop receiver_klass() { return nm->receiver_klass(); }
00232
00233 static void print_title(outputStream* st) {
00234 st->print(" Opt");
00235 pnode::print_title(st);
00236 }
00237
00238 void print(outputStream* st, int total_ticks) {
00239 pnode::print(st, total_ticks);
00240 }
00241
00242 void print_method_on(outputStream* st) {
00243 if (nm->isUncommonRecompiled()) {
00244 st->print("Uncommom recompiled ");
00245 }
00246 pnode::print_method_on(st);
00247 if (CompilerDebug) {
00248 st->print(" %#x ", nm);
00249 }
00250 }
00251 };
00252
00253 int FlatProfiler::entry(int value) {
00254 return value % table_size;
00255 }
00256
00257 void FlatProfiler::interpreted_update(methodOop method, klassOop klass, TickPosition where) {
00258 int index = entry(method->selector_or_method()->identity_hash());
00259 if (!table[index]) {
00260 table[index] = new interpretedNode(method, klass, where);
00261 } else {
00262 for(pnode* node = table[index]; node; node = node->next()) {
00263 if (node->match(method, klass)) {
00264 node->update(where);
00265 return;
00266 }
00267 if (!node->next())
00268 node->set_next(new interpretedNode(method, klass, where));
00269 }
00270 }
00271 }
00272
00273 void FlatProfiler::compiled_update(nmethod* nm, TickPosition where) {
00274 int index = entry(nm->main_id.major());
00275 if (!table[index]) {
00276 table[index] = new compiledNode(nm, where);
00277 } else {
00278 for(pnode* node = table[index]; node; node = node->next()) {
00279 if (node->match(nm)) {
00280 node->update(where);
00281 return;
00282 }
00283 if (!node->next())
00284 node->set_next(new compiledNode(nm, where));
00285 }
00286 }
00287 }
00288
00289 class FlatProfilerTask : public PeriodicTask {
00290 public:
00291 FlatProfilerTask(int interval_time) : PeriodicTask(interval_time) {}
00292 void task();
00293 };
00294
00295 void FlatProfilerTask::task() {
00296
00297 if (FlatProfiler::proc == NULL) return;
00298 if (DeltaProcess::active() == FlatProfiler::proc || UseGlobalFlatProfiling) {
00299 FlatProfiler::record_tick();
00300 }
00301 }
00302
00303 void FlatProfiler::record_tick_for_running_frame(frame fr) {
00304
00305 if (fr.is_interpreted_frame()) {
00306 methodOop method = fr.method();
00307 if (method == NULL) return;
00308 assert(method->is_method(), "must be method");
00309 FlatProfiler::interpreted_update(method, fr.receiver()->klass(), in_code);
00310
00311 } else if (fr.is_compiled_frame()) {
00312 FlatProfiler::compiled_update(findNMethod(fr.pc()), in_code);
00313
00314 } else if (PIC::in_heap(fr.pc())) {
00315 PIC* pic = PIC::find(fr.pc());
00316 FlatProfiler::compiled_update(findNMethod((char*) pic->compiled_ic()), in_pic);
00317
00318 } else if (StubRoutines::contains(fr.pc())) {
00319 FlatProfiler::stub_ticks++;
00320 }
00321 }
00322
00323 void FlatProfiler::record_tick_for_calling_frame(frame fr) {
00324
00325
00326 TickPosition where = other;
00327 if (theCompiler) {
00328 where = in_compiler;
00329 }
00330 if (fr.is_interpreted_frame()) {
00331 methodOop method = fr.method();
00332 if (method == NULL) return;
00333 assert(method->is_method(), "must be method");
00334 int bci = method->bci_from(fr.hp());
00335 if (Bytecodes::code_type((Bytecodes::Code) *method->codes(bci)) == Bytecodes::primitive_call) {
00336 where = in_primitive;
00337 }
00338 FlatProfiler::interpreted_update(method, fr.receiver()->klass(), where);
00339
00340 } else if (fr.is_compiled_frame()) {
00341 nmethod* nm = findNMethod(fr.pc());
00342 relocIterator iter(nm);
00343 while (iter.next()) {
00344 if (iter.is_call() && iter.call_end() == fr.pc()) {
00345 if (iter.type() == relocInfo::prim_type)
00346 where = in_primitive;
00347 }
00348 }
00349 FlatProfiler::compiled_update(nm, where);
00350
00351 } else {
00352 if (StubRoutines::contains(fr.pc())) {
00353 FlatProfiler::stub_ticks++;
00354 } else {
00355 FlatProfiler::unknown_ticks++;
00356 }
00357 }
00358 }
00359
00360 void FlatProfiler::record_tick() {
00361
00362 if (DeltaProcess::is_idle()) return;
00363
00364
00365 if (theCompiler) { FlatProfiler::compiler_ticks++; }
00366 if (GCInProgress) { FlatProfiler::gc_ticks++; return; }
00367 if (processSemaphore) { FlatProfiler::semaphore_ticks++; return; }
00368
00369 { FlagSetting(processSemaphore, true);
00370 DeltaProcess* p = DeltaProcess::active();
00371 if (p->last_Delta_fp()) {
00372 record_tick_for_calling_frame(p->last_frame());
00373 } else {
00374 record_tick_for_running_frame(p->profile_top_frame());
00375 }
00376 }
00377 }
00378
00379 void FlatProfiler::allocate_table() {
00380 table = NEW_C_HEAP_ARRAY(pnode*, table_size);
00381 for(int index = 0; index < table_size; index++)
00382 table[index] = NULL;
00383 }
00384
00385 void FlatProfiler::reset() {
00386 proc = NULL;
00387 task = NULL;
00388
00389 for(int index = 0; index < table_size; index++) {
00390 pnode* n = table[index];
00391 if (n) {
00392 delete n;
00393 table[index] = NULL;
00394 }
00395 }
00396
00397 gc_ticks = 0;
00398 unknown_ticks = 0;
00399 semaphore_ticks = 0;
00400 compiler_ticks = 0;
00401 stub_ticks = 0;
00402 }
00403
00404 void FlatProfiler::engage(DeltaProcess* p) {
00405 proc = p;
00406 if (task == NULL) {
00407 task = new FlatProfilerTask(10);
00408 task->enroll();
00409 time.start();
00410 }
00411 }
00412
00413 DeltaProcess* FlatProfiler::disengage() {
00414 if (!task) return NULL;
00415 task->deroll();
00416 delete task;
00417 task = NULL;
00418 time.stop();
00419 DeltaProcess* p = process();
00420 proc = NULL;
00421 return proc;
00422 }
00423
00424 bool FlatProfiler::is_active() {
00425 return task != NULL;
00426 }
00427
00428 static int compare_nodes(const void* p1, const void* p2) {
00429 pnode** pn1 = (pnode**)p1;
00430 pnode** pn2 = (pnode**)p2;
00431 return (*pn2)->total_ticks() - (*pn1)->total_ticks();
00432 }
00433
00434
00435 void print_ticks(char* title, int ticks, int total) {
00436 if (ticks>0)
00437 std->print_cr("%5.1f%% %3d %s", ticks * 100.0 / total, ticks, title);
00438 }
00439
00440 void FlatProfiler::print(int cutoff) {
00441 #ifdef PRODUCT
00442
00443 #else
00444 FlagSetting f(PrintObjectID, false);
00445 ResourceMark rm;
00446 double secs = time.seconds();
00447
00448 GrowableArray <pnode*>* array = new GrowableArray<pnode*>(200);
00449
00450 for(int index = 0; index < table_size; index++) {
00451 for(pnode* node = table[index]; node; node = node->next())
00452 array->append(node);
00453 }
00454
00455 array->sort(&pnode::compare);
00456
00457
00458 int total = total_ticks();
00459 for (index = 0; index < array->length(); index++) {
00460 total += array->at(index)->ticks.total();
00461 }
00462
00463 std->cr();
00464 std->print_cr("Flatprofile %3.2f secs (%d ticks):", secs, total);
00465 std->cr();
00466
00467
00468 tick_counter interpreted_ticks;
00469 bool has_interpreted_ticks = false;
00470 int print_count = 0;
00471 for (index = 0; index < array->length(); index++) {
00472 pnode* n = array->at(index);
00473 if (n->is_interpreted()) {
00474 interpreted_ticks.add(&n->ticks);
00475 if (!has_interpreted_ticks) {
00476 interpretedNode::print_title(std);
00477 has_interpreted_ticks = true;
00478 }
00479 if (print_count++ < ProfilerNumberOfInterpreterMethods) {
00480 n->print(std, total);
00481 }
00482 }
00483 }
00484 if (has_interpreted_ticks) {
00485 tick_counter others;
00486 for ( ; index < array->length(); index++) others.add(&array->at(index)->ticks);
00487 if (others.total() > 0) {
00488 interpretedNode::print_total(std, &interpreted_ticks, total, "(all above)");
00489 interpretedNode::print_total(std, &others, total, "(all others)");
00490 }
00491 interpreted_ticks.add(&others);
00492 interpretedNode::print_total(std, &interpreted_ticks, total, "Total interpreted");
00493 std->cr();
00494 }
00495
00496
00497 print_count = 0;
00498 bool has_compiled_ticks = false;
00499 tick_counter compiled_ticks;
00500 for (index = 0; index < array->length(); index++) {
00501 pnode* n = array->at(index);
00502 if (n->is_compiled()) {
00503 compiled_ticks.add(&n->ticks);
00504 if (!has_compiled_ticks) {
00505 compiledNode::print_title(std);
00506 has_compiled_ticks = true;
00507 }
00508 if (print_count++ < ProfilerNumberOfCompiledMethods) {
00509 n->print(std, total);
00510 }
00511 }
00512 }
00513
00514 if (has_compiled_ticks) {
00515 tick_counter others;
00516 for ( ; index < array->length(); index++) others.add(&array->at(index)->ticks);
00517 if (others.total() > 0) {
00518 compiledNode::print_total(std, &compiled_ticks, total, "(all above)");
00519 compiledNode::print_total(std, &others, total, "(all others)");
00520 }
00521 compiled_ticks.add(&others);
00522 compiledNode::print_total(std, &compiled_ticks, total, "Total compiled");
00523 std->cr();
00524 }
00525
00526 std->cr();
00527
00528 if (total_ticks() > 0) {
00529 std->print_cr(" Additional ticks:");
00530 print_ticks("Garbage collector", gc_ticks, total);
00531 print_ticks("Process semaphore", semaphore_ticks, total);
00532 print_ticks("Unknown code", unknown_ticks, total);
00533 print_ticks("Stub routines", stub_ticks, total);
00534 print_ticks("Total compilation (already included above)", compiler_ticks, total);
00535 }
00536 #endif
00537 }
00538
00539 void fprofiler_init() {
00540 FlatProfiler::allocate_table();
00541 }