354 // resolution) as well as recursive calls of the same event type could happen. |
354 // resolution) as well as recursive calls of the same event type could happen. |
355 // Only one elapsed timer (cumulative) and one thread-local self timer (exclusive) |
355 // Only one elapsed timer (cumulative) and one thread-local self timer (exclusive) |
356 // (i.e. only one event type) are active at a time even multiple PerfClassTraceTime |
356 // (i.e. only one event type) are active at a time even multiple PerfClassTraceTime |
357 // instances have been created as multiple events are happening. |
357 // instances have been created as multiple events are happening. |
358 class PerfClassTraceTime { |
358 class PerfClassTraceTime { |
359 public: |
359 public: |
360 enum { |
360 enum { |
361 CLASS_LOAD = 0, |
361 CLASS_LOAD = 0, |
362 PARSE_CLASS = 1, |
362 PARSE_CLASS = 1, |
363 CLASS_LINK = 2, |
363 CLASS_LINK = 2, |
364 CLASS_VERIFY = 3, |
364 CLASS_VERIFY = 3, |
365 CLASS_CLINIT = 4, |
365 CLASS_CLINIT = 4, |
366 DEFINE_CLASS = 5, |
366 DEFINE_CLASS = 5, |
367 EVENT_TYPE_COUNT = 6 |
367 EVENT_TYPE_COUNT = 6 |
368 }; |
368 }; |
369 protected: |
369 protected: |
370 // _t tracks time from initialization to destruction of this timer instance |
370 // _t tracks time from initialization to destruction of this timer instance |
371 // including time for all other event types, and recursive calls of this type. |
371 // including time for all other event types, and recursive calls of this type. |
372 // When a timer is called recursively, the elapsedTimer _t would not be used. |
372 // When a timer is called recursively, the elapsedTimer _t would not be used. |
373 elapsedTimer _t; |
373 elapsedTimer _t; |
374 PerfLongCounter* _timep; |
374 PerfLongCounter* _timep; |
375 PerfLongCounter* _selftimep; |
375 PerfLongCounter* _selftimep; |
376 PerfLongCounter* _eventp; |
376 PerfLongCounter* _eventp; |
377 // pointer to thread-local recursion counter and timer array |
377 // pointer to thread-local recursion counter and timer array |
378 // The thread_local timers track cumulative time for specific event types |
378 // The thread_local timers track cumulative time for specific event types |
379 // exclusive of time for other event types, but including recursive calls |
379 // exclusive of time for other event types, but including recursive calls |
380 // of the same type. |
380 // of the same type. |
381 int* _recursion_counters; |
381 int* _recursion_counters; |
382 elapsedTimer* _timers; |
382 elapsedTimer* _timers; |
383 int _event_type; |
383 int _event_type; |
384 int _prev_active_event; |
384 int _prev_active_event; |
385 |
385 |
386 public: |
386 public: |
387 |
387 |
388 inline PerfClassTraceTime(PerfLongCounter* timep, /* counter incremented with inclusive time */ |
388 inline PerfClassTraceTime(PerfLongCounter* timep, /* counter incremented with inclusive time */ |
389 PerfLongCounter* selftimep, /* counter incremented with exclusive time */ |
389 PerfLongCounter* selftimep, /* counter incremented with exclusive time */ |
390 PerfLongCounter* eventp, /* event counter */ |
390 PerfLongCounter* eventp, /* event counter */ |
391 int* recursion_counters, /* thread-local recursion counter array */ |
391 int* recursion_counters, /* thread-local recursion counter array */ |
392 elapsedTimer* timers, /* thread-local timer array */ |
392 elapsedTimer* timers, /* thread-local timer array */ |
393 int type /* event type */ ) : |
393 int type /* event type */ ) : |
394 _timep(timep), _selftimep(selftimep), _eventp(eventp), _recursion_counters(recursion_counters), _timers(timers), _event_type(type) { |
394 _timep(timep), _selftimep(selftimep), _eventp(eventp), _recursion_counters(recursion_counters), _timers(timers), _event_type(type) { |
395 initialize(); |
395 initialize(); |
396 } |
396 } |
397 |
397 |
398 inline PerfClassTraceTime(PerfLongCounter* timep, /* counter incremented with inclusive time */ |
398 inline PerfClassTraceTime(PerfLongCounter* timep, /* counter incremented with inclusive time */ |
399 elapsedTimer* timers, /* thread-local timer array */ |
399 elapsedTimer* timers, /* thread-local timer array */ |
400 int type /* event type */ ) : |
400 int type /* event type */ ) : |
401 _timep(timep), _selftimep(NULL), _eventp(NULL), _recursion_counters(NULL), _timers(timers), _event_type(type) { |
401 _timep(timep), _selftimep(NULL), _eventp(NULL), _recursion_counters(NULL), _timers(timers), _event_type(type) { |
402 initialize(); |
402 initialize(); |
403 } |
403 } |
404 |
404 |
405 void initialize() { |
405 inline void suspend() { _t.stop(); _timers[_event_type].stop(); } |
406 if (!UsePerfData) return; |
406 inline void resume() { _t.start(); _timers[_event_type].start(); } |
407 |
407 |
408 if (_eventp != NULL) { |
408 ~PerfClassTraceTime(); |
409 // increment the event counter |
409 void initialize(); |
410 _eventp->inc(); |
410 }; |
411 } |
|
412 |
|
413 // stop the current active thread-local timer to measure inclusive time |
|
414 _prev_active_event = -1; |
|
415 for (int i=0; i < EVENT_TYPE_COUNT; i++) { |
|
416 if (_timers[i].is_active()) { |
|
417 assert(_prev_active_event == -1, "should have only one active timer"); |
|
418 _prev_active_event = i; |
|
419 _timers[i].stop(); |
|
420 } |
|
421 } |
|
422 |
|
423 if (_recursion_counters == NULL || (_recursion_counters[_event_type])++ == 0) { |
|
424 // start the inclusive timer if not recursively called |
|
425 _t.start(); |
|
426 } |
|
427 |
|
428 // start thread-local timer of the given event type |
|
429 if (!_timers[_event_type].is_active()) { |
|
430 _timers[_event_type].start(); |
|
431 } |
|
432 } |
|
433 |
|
434 inline void suspend() { _t.stop(); _timers[_event_type].stop(); } |
|
435 inline void resume() { _t.start(); _timers[_event_type].start(); } |
|
436 |
|
437 ~PerfClassTraceTime() { |
|
438 if (!UsePerfData) return; |
|
439 |
|
440 // stop the thread-local timer as the event completes |
|
441 // and resume the thread-local timer of the event next on the stack |
|
442 _timers[_event_type].stop(); |
|
443 jlong selftime = _timers[_event_type].ticks(); |
|
444 |
|
445 if (_prev_active_event >= 0) { |
|
446 _timers[_prev_active_event].start(); |
|
447 } |
|
448 |
|
449 if (_recursion_counters != NULL && --(_recursion_counters[_event_type]) > 0) return; |
|
450 |
|
451 // increment the counters only on the leaf call |
|
452 _t.stop(); |
|
453 _timep->inc(_t.ticks()); |
|
454 if (_selftimep != NULL) { |
|
455 _selftimep->inc(selftime); |
|
456 } |
|
457 // add all class loading related event selftime to the accumulated time counter |
|
458 ClassLoader::perf_accumulated_time()->inc(selftime); |
|
459 |
|
460 // reset the timer |
|
461 _timers[_event_type].reset(); |
|
462 } |
|
463 }; |
|
464 |
|
465 |
411 |
466 #endif // SHARE_VM_CLASSFILE_CLASSLOADER_HPP |
412 #endif // SHARE_VM_CLASSFILE_CLASSLOADER_HPP |