# HG changeset patch # User mchung # Date 1247249400 25200 # Node ID 224791e7ecab1b500d8902203bb53647db623fc1 # Parent 9b4390b8c6f7811196cfdcf12f1878a3a951bbbe 6857194: Add hotspot perf counters to aid class loading performance measurement Summary: Add new jvmstat counters to measure detailed class loading time Reviewed-by: acorn, kamg diff -r 9b4390b8c6f7 -r 224791e7ecab hotspot/src/share/vm/classfile/classFileParser.cpp --- a/hotspot/src/share/vm/classfile/classFileParser.cpp Fri Jun 19 07:33:25 2009 -0700 +++ b/hotspot/src/share/vm/classfile/classFileParser.cpp Fri Jul 10 11:10:00 2009 -0700 @@ -547,7 +547,6 @@ int length, Handle class_loader, Handle protection_domain, - PerfTraceTime* vmtimer, symbolHandle class_name, TRAPS) { ClassFileStream* cfs = stream(); @@ -575,13 +574,11 @@ guarantee_property(unresolved_klass->byte_at(0) != JVM_SIGNATURE_ARRAY, "Bad interface name in class file %s", CHECK_(nullHandle)); - vmtimer->suspend(); // do not count recursive loading twice // Call resolve_super so classcircularity is checked klassOop k = SystemDictionary::resolve_super_or_fail(class_name, unresolved_klass, class_loader, protection_domain, false, CHECK_(nullHandle)); interf = KlassHandle(THREAD, k); - vmtimer->resume(); if (LinkWellKnownClasses) // my super type is well known to me cp->klass_at_put(interface_index, interf()); // eagerly resolve @@ -2558,7 +2555,15 @@ ClassFileStream* cfs = stream(); // Timing - PerfTraceTime vmtimer(ClassLoader::perf_accumulated_time()); + assert(THREAD->is_Java_thread(), "must be a JavaThread"); + JavaThread* jt = (JavaThread*) THREAD; + + PerfClassTraceTime ctimer(ClassLoader::perf_class_parse_time(), + ClassLoader::perf_class_parse_selftime(), + NULL, + jt->get_thread_stat()->perf_recursion_counts_addr(), + jt->get_thread_stat()->perf_timers_addr(), + PerfClassTraceTime::PARSE_CLASS); _has_finalizer = _has_empty_finalizer = _has_vanilla_constructor = false; @@ -2738,7 +2743,7 @@ if (itfs_len == 0) { local_interfaces = objArrayHandle(THREAD, Universe::the_empty_system_obj_array()); } else { - local_interfaces = parse_interfaces(cp, itfs_len, class_loader, protection_domain, &vmtimer, _class_name, CHECK_(nullHandle)); + local_interfaces = parse_interfaces(cp, itfs_len, class_loader, protection_domain, _class_name, CHECK_(nullHandle)); } // Fields (offsets are filled in later) @@ -2782,6 +2787,7 @@ protection_domain, true, CHECK_(nullHandle)); + KlassHandle kh (THREAD, k); super_klass = instanceKlassHandle(THREAD, kh()); if (LinkWellKnownClasses) // my super class is well known to me diff -r 9b4390b8c6f7 -r 224791e7ecab hotspot/src/share/vm/classfile/classFileParser.hpp --- a/hotspot/src/share/vm/classfile/classFileParser.hpp Fri Jun 19 07:33:25 2009 -0700 +++ b/hotspot/src/share/vm/classfile/classFileParser.hpp Fri Jul 10 11:10:00 2009 -0700 @@ -61,7 +61,6 @@ int length, Handle class_loader, Handle protection_domain, - PerfTraceTime* vmtimer, symbolHandle class_name, TRAPS); diff -r 9b4390b8c6f7 -r 224791e7ecab hotspot/src/share/vm/classfile/classLoader.cpp --- a/hotspot/src/share/vm/classfile/classLoader.cpp Fri Jun 19 07:33:25 2009 -0700 +++ b/hotspot/src/share/vm/classfile/classLoader.cpp Fri Jul 10 11:10:00 2009 -0700 @@ -48,9 +48,26 @@ PerfCounter* ClassLoader::_perf_accumulated_time = NULL; PerfCounter* ClassLoader::_perf_classes_inited = NULL; PerfCounter* ClassLoader::_perf_class_init_time = NULL; +PerfCounter* ClassLoader::_perf_class_init_selftime = NULL; +PerfCounter* ClassLoader::_perf_classes_verified = NULL; PerfCounter* ClassLoader::_perf_class_verify_time = NULL; +PerfCounter* ClassLoader::_perf_class_verify_selftime = NULL; PerfCounter* ClassLoader::_perf_classes_linked = NULL; PerfCounter* ClassLoader::_perf_class_link_time = NULL; +PerfCounter* ClassLoader::_perf_class_link_selftime = NULL; +PerfCounter* ClassLoader::_perf_class_parse_time = NULL; +PerfCounter* ClassLoader::_perf_class_parse_selftime = NULL; +PerfCounter* ClassLoader::_perf_sys_class_lookup_time = NULL; +PerfCounter* ClassLoader::_perf_shared_classload_time = NULL; +PerfCounter* ClassLoader::_perf_sys_classload_time = NULL; +PerfCounter* ClassLoader::_perf_app_classload_time = NULL; +PerfCounter* ClassLoader::_perf_app_classload_selftime = NULL; +PerfCounter* ClassLoader::_perf_app_classload_count = NULL; +PerfCounter* ClassLoader::_perf_define_appclasses = NULL; +PerfCounter* ClassLoader::_perf_define_appclass_time = NULL; +PerfCounter* ClassLoader::_perf_define_appclass_selftime = NULL; +PerfCounter* ClassLoader::_perf_app_classfile_bytes_read = NULL; +PerfCounter* ClassLoader::_perf_sys_classfile_bytes_read = NULL; PerfCounter* ClassLoader::_sync_systemLoaderLockContentionRate = NULL; PerfCounter* ClassLoader::_sync_nonSystemLoaderLockContentionRate = NULL; PerfCounter* ClassLoader::_sync_JVMFindLoadedClassLockFreeCounter = NULL; @@ -152,6 +169,9 @@ hpi::close(file_handle); // construct ClassFileStream if (num_read == (size_t)st.st_size) { + if (UsePerfData) { + ClassLoader::perf_sys_classfile_bytes_read()->inc(num_read); + } return new ClassFileStream(buffer, st.st_size, _dir); // Resource allocated } } @@ -198,6 +218,9 @@ buffer = NEW_RESOURCE_ARRAY(u1, filesize); if (!(*ReadEntry)(_zip, entry, buffer, filename)) return NULL; } + if (UsePerfData) { + ClassLoader::perf_sys_classfile_bytes_read()->inc(filesize); + } // return result return new ClassFileStream(buffer, filesize, _zip_name); // Resource allocated } @@ -825,7 +848,9 @@ ClassFileStream* stream = NULL; int classpath_index = 0; { - PerfTraceTime vmtimer(perf_accumulated_time()); + PerfClassTraceTime vmtimer(perf_sys_class_lookup_time(), + ((JavaThread*) THREAD)->get_thread_stat()->perf_timers_addr(), + PerfClassTraceTime::CLASS_LOAD); ClassPathEntry* e = _first_entry; while (e != NULL) { stream = e->open_stream(name); @@ -890,11 +915,29 @@ // jvmstat performance counters NEWPERFTICKCOUNTER(_perf_accumulated_time, SUN_CLS, "time"); NEWPERFTICKCOUNTER(_perf_class_init_time, SUN_CLS, "classInitTime"); + NEWPERFTICKCOUNTER(_perf_class_init_selftime, SUN_CLS, "classInitTime.self"); NEWPERFTICKCOUNTER(_perf_class_verify_time, SUN_CLS, "classVerifyTime"); + NEWPERFTICKCOUNTER(_perf_class_verify_selftime, SUN_CLS, "classVerifyTime.self"); NEWPERFTICKCOUNTER(_perf_class_link_time, SUN_CLS, "classLinkedTime"); - + NEWPERFTICKCOUNTER(_perf_class_link_selftime, SUN_CLS, "classLinkedTime.self"); NEWPERFEVENTCOUNTER(_perf_classes_inited, SUN_CLS, "initializedClasses"); NEWPERFEVENTCOUNTER(_perf_classes_linked, SUN_CLS, "linkedClasses"); + NEWPERFEVENTCOUNTER(_perf_classes_verified, SUN_CLS, "verifiedClasses"); + + NEWPERFTICKCOUNTER(_perf_class_parse_time, SUN_CLS, "parseClassTime"); + NEWPERFTICKCOUNTER(_perf_class_parse_selftime, SUN_CLS, "parseClassTime.self"); + NEWPERFTICKCOUNTER(_perf_sys_class_lookup_time, SUN_CLS, "lookupSysClassTime"); + NEWPERFTICKCOUNTER(_perf_shared_classload_time, SUN_CLS, "sharedClassLoadTime"); + NEWPERFTICKCOUNTER(_perf_sys_classload_time, SUN_CLS, "sysClassLoadTime"); + NEWPERFTICKCOUNTER(_perf_app_classload_time, SUN_CLS, "appClassLoadTime"); + NEWPERFTICKCOUNTER(_perf_app_classload_selftime, SUN_CLS, "appClassLoadTime.self"); + NEWPERFEVENTCOUNTER(_perf_app_classload_count, SUN_CLS, "appClassLoadCount"); + NEWPERFTICKCOUNTER(_perf_define_appclasses, SUN_CLS, "defineAppClasses"); + NEWPERFTICKCOUNTER(_perf_define_appclass_time, SUN_CLS, "defineAppClassTime"); + NEWPERFTICKCOUNTER(_perf_define_appclass_selftime, SUN_CLS, "defineAppClassTime.self"); + NEWPERFBYTECOUNTER(_perf_app_classfile_bytes_read, SUN_CLS, "appClassBytes"); + NEWPERFBYTECOUNTER(_perf_sys_classfile_bytes_read, SUN_CLS, "sysClassBytes"); + // The following performance counters are added for measuring the impact // of the bug fix of 6365597. They are mainly focused on finding out diff -r 9b4390b8c6f7 -r 224791e7ecab hotspot/src/share/vm/classfile/classLoader.hpp --- a/hotspot/src/share/vm/classfile/classLoader.hpp Fri Jun 19 07:33:25 2009 -0700 +++ b/hotspot/src/share/vm/classfile/classLoader.hpp Fri Jul 10 11:10:00 2009 -0700 @@ -149,9 +149,26 @@ static PerfCounter* _perf_accumulated_time; static PerfCounter* _perf_classes_inited; static PerfCounter* _perf_class_init_time; + static PerfCounter* _perf_class_init_selftime; + static PerfCounter* _perf_classes_verified; static PerfCounter* _perf_class_verify_time; + static PerfCounter* _perf_class_verify_selftime; static PerfCounter* _perf_classes_linked; static PerfCounter* _perf_class_link_time; + static PerfCounter* _perf_class_link_selftime; + static PerfCounter* _perf_class_parse_time; + static PerfCounter* _perf_class_parse_selftime; + static PerfCounter* _perf_sys_class_lookup_time; + static PerfCounter* _perf_shared_classload_time; + static PerfCounter* _perf_sys_classload_time; + static PerfCounter* _perf_app_classload_time; + static PerfCounter* _perf_app_classload_selftime; + static PerfCounter* _perf_app_classload_count; + static PerfCounter* _perf_define_appclasses; + static PerfCounter* _perf_define_appclass_time; + static PerfCounter* _perf_define_appclass_selftime; + static PerfCounter* _perf_app_classfile_bytes_read; + static PerfCounter* _perf_sys_classfile_bytes_read; static PerfCounter* _sync_systemLoaderLockContentionRate; static PerfCounter* _sync_nonSystemLoaderLockContentionRate; @@ -196,12 +213,29 @@ static void print_bootclasspath(); // Timing - static PerfCounter* perf_accumulated_time() { return _perf_accumulated_time; } - static PerfCounter* perf_classes_inited() { return _perf_classes_inited; } - static PerfCounter* perf_class_init_time() { return _perf_class_init_time; } - static PerfCounter* perf_class_verify_time() { return _perf_class_verify_time; } - static PerfCounter* perf_classes_linked() { return _perf_classes_linked; } - static PerfCounter* perf_class_link_time() { return _perf_class_link_time; } + static PerfCounter* perf_accumulated_time() { return _perf_accumulated_time; } + static PerfCounter* perf_classes_inited() { return _perf_classes_inited; } + static PerfCounter* perf_class_init_time() { return _perf_class_init_time; } + static PerfCounter* perf_class_init_selftime() { return _perf_class_init_selftime; } + static PerfCounter* perf_classes_verified() { return _perf_classes_verified; } + static PerfCounter* perf_class_verify_time() { return _perf_class_verify_time; } + static PerfCounter* perf_class_verify_selftime() { return _perf_class_verify_selftime; } + static PerfCounter* perf_classes_linked() { return _perf_classes_linked; } + static PerfCounter* perf_class_link_time() { return _perf_class_link_time; } + static PerfCounter* perf_class_link_selftime() { return _perf_class_link_selftime; } + static PerfCounter* perf_class_parse_time() { return _perf_class_parse_time; } + static PerfCounter* perf_class_parse_selftime() { return _perf_class_parse_selftime; } + static PerfCounter* perf_sys_class_lookup_time() { return _perf_sys_class_lookup_time; } + static PerfCounter* perf_shared_classload_time() { return _perf_shared_classload_time; } + static PerfCounter* perf_sys_classload_time() { return _perf_sys_classload_time; } + static PerfCounter* perf_app_classload_time() { return _perf_app_classload_time; } + static PerfCounter* perf_app_classload_selftime() { return _perf_app_classload_selftime; } + static PerfCounter* perf_app_classload_count() { return _perf_app_classload_count; } + static PerfCounter* perf_define_appclasses() { return _perf_define_appclasses; } + static PerfCounter* perf_define_appclass_time() { return _perf_define_appclass_time; } + static PerfCounter* perf_define_appclass_selftime() { return _perf_define_appclass_selftime; } + static PerfCounter* perf_app_classfile_bytes_read() { return _perf_app_classfile_bytes_read; } + static PerfCounter* perf_sys_classfile_bytes_read() { return _perf_sys_classfile_bytes_read; } // Record how often system loader lock object is contended static PerfCounter* sync_systemLoaderLockContentionRate() { @@ -307,3 +341,118 @@ static int compile_the_world_counter() { return _compile_the_world_counter; } #endif //PRODUCT }; + +// PerfClassTraceTime is used to measure time for class loading related events. +// This class tracks cumulative time and exclusive time for specific event types. +// During the execution of one event, other event types (e.g. class loading and +// resolution) as well as recursive calls of the same event type could happen. +// Only one elapsed timer (cumulative) and one thread-local self timer (exclusive) +// (i.e. only one event type) are active at a time even multiple PerfClassTraceTime +// instances have been created as multiple events are happening. +class PerfClassTraceTime { + public: + enum { + CLASS_LOAD = 0, + PARSE_CLASS = 1, + CLASS_LINK = 2, + CLASS_VERIFY = 3, + CLASS_CLINIT = 4, + DEFINE_CLASS = 5, + EVENT_TYPE_COUNT = 6 + }; + protected: + // _t tracks time from initialization to destruction of this timer instance + // including time for all other event types, and recursive calls of this type. + // When a timer is called recursively, the elapsedTimer _t would not be used. + elapsedTimer _t; + PerfLongCounter* _timep; + PerfLongCounter* _selftimep; + PerfLongCounter* _eventp; + // pointer to thread-local recursion counter and timer array + // The thread_local timers track cumulative time for specific event types + // exclusive of time for other event types, but including recursive calls + // of the same type. + int* _recursion_counters; + elapsedTimer* _timers; + int _event_type; + int _prev_active_event; + + public: + + inline PerfClassTraceTime(PerfLongCounter* timep, /* counter incremented with inclusive time */ + PerfLongCounter* selftimep, /* counter incremented with exclusive time */ + PerfLongCounter* eventp, /* event counter */ + int* recursion_counters, /* thread-local recursion counter array */ + elapsedTimer* timers, /* thread-local timer array */ + int type /* event type */ ) : + _timep(timep), _selftimep(selftimep), _eventp(eventp), _recursion_counters(recursion_counters), _timers(timers), _event_type(type) { + initialize(); + } + + inline PerfClassTraceTime(PerfLongCounter* timep, /* counter incremented with inclusive time */ + elapsedTimer* timers, /* thread-local timer array */ + int type /* event type */ ) : + _timep(timep), _selftimep(NULL), _eventp(NULL), _recursion_counters(NULL), _timers(timers), _event_type(type) { + initialize(); + } + + void initialize() { + if (!UsePerfData) return; + + if (_eventp != NULL) { + // increment the event counter + _eventp->inc(); + } + + // stop the current active thread-local timer to measure inclusive time + _prev_active_event = -1; + for (int i=0; i < EVENT_TYPE_COUNT; i++) { + if (_timers[i].is_active()) { + assert(_prev_active_event == -1, "should have only one active timer"); + _prev_active_event = i; + _timers[i].stop(); + } + } + + if (_recursion_counters == NULL || (_recursion_counters[_event_type])++ == 0) { + // start the inclusive timer if not recursively called + _t.start(); + } + + // start thread-local timer of the given event type + if (!_timers[_event_type].is_active()) { + _timers[_event_type].start(); + } + } + + inline void suspend() { _t.stop(); _timers[_event_type].stop(); } + inline void resume() { _t.start(); _timers[_event_type].start(); } + + ~PerfClassTraceTime() { + if (!UsePerfData) return; + + // stop the thread-local timer as the event completes + // and resume the thread-local timer of the event next on the stack + _timers[_event_type].stop(); + jlong selftime = _timers[_event_type].ticks(); + + if (_prev_active_event >= 0) { + _timers[_prev_active_event].start(); + } + + if (_recursion_counters != NULL && --(_recursion_counters[_event_type]) > 0) return; + + // increment the counters only on the leaf call + _t.stop(); + _timep->inc(_t.ticks()); + if (_selftimep != NULL) { + _selftimep->inc(selftime); + } + // add all class loading related event selftime to the accumulated time counter + ClassLoader::perf_accumulated_time()->inc(selftime); + + // reset the timer + _timers[_event_type].reset(); + } +}; + diff -r 9b4390b8c6f7 -r 224791e7ecab hotspot/src/share/vm/classfile/systemDictionary.cpp --- a/hotspot/src/share/vm/classfile/systemDictionary.cpp Fri Jun 19 07:33:25 2009 -0700 +++ b/hotspot/src/share/vm/classfile/systemDictionary.cpp Fri Jul 10 11:10:00 2009 -0700 @@ -1306,13 +1306,18 @@ instanceKlassHandle SystemDictionary::load_instance_class(symbolHandle class_name, Handle class_loader, TRAPS) { instanceKlassHandle nh = instanceKlassHandle(); // null Handle if (class_loader.is_null()) { + // Search the shared system dictionary for classes preloaded into the // shared spaces. instanceKlassHandle k; - k = load_shared_class(class_name, class_loader, THREAD); + { + PerfTraceTime vmtimer(ClassLoader::perf_shared_classload_time()); + k = load_shared_class(class_name, class_loader, THREAD); + } if (k.is_null()) { // Use VM class loader + PerfTraceTime vmtimer(ClassLoader::perf_sys_classload_time()); k = ClassLoader::load_classfile(class_name, CHECK_(nh)); } @@ -1334,6 +1339,16 @@ // Use user specified class loader to load class. Call loadClass operation on class_loader. ResourceMark rm(THREAD); + assert(THREAD->is_Java_thread(), "must be a JavaThread"); + JavaThread* jt = (JavaThread*) THREAD; + + PerfClassTraceTime vmtimer(ClassLoader::perf_app_classload_time(), + ClassLoader::perf_app_classload_selftime(), + ClassLoader::perf_app_classload_count(), + jt->get_thread_stat()->perf_recursion_counts_addr(), + jt->get_thread_stat()->perf_timers_addr(), + PerfClassTraceTime::CLASS_LOAD); + Handle s = java_lang_String::create_from_symbol(class_name, CHECK_(nh)); // Translate to external class name format, i.e., convert '/' chars to '.' Handle string = java_lang_String::externalize_classname(s, CHECK_(nh)); diff -r 9b4390b8c6f7 -r 224791e7ecab hotspot/src/share/vm/includeDB_core --- a/hotspot/src/share/vm/includeDB_core Fri Jun 19 07:33:25 2009 -0700 +++ b/hotspot/src/share/vm/includeDB_core Fri Jul 10 11:10:00 2009 -0700 @@ -874,6 +874,7 @@ classFileParser.cpp symbolOop.hpp classFileParser.cpp symbolTable.hpp classFileParser.cpp systemDictionary.hpp +classFileParser.cpp threadService.hpp classFileParser.cpp timer.hpp classFileParser.cpp universe.inline.hpp classFileParser.cpp verificationType.hpp @@ -926,6 +927,7 @@ classLoader.cpp symbolOop.hpp classLoader.cpp systemDictionary.hpp classLoader.cpp threadCritical.hpp +classLoader.cpp threadService.hpp classLoader.cpp timer.hpp classLoader.cpp universe.inline.hpp classLoader.cpp vmSymbols.hpp @@ -4026,6 +4028,7 @@ systemDictionary.cpp resolutionErrors.hpp systemDictionary.cpp signature.hpp systemDictionary.cpp systemDictionary.hpp +systemDictionary.cpp threadService.hpp systemDictionary.cpp typeArrayKlass.hpp systemDictionary.cpp vmSymbols.hpp diff -r 9b4390b8c6f7 -r 224791e7ecab hotspot/src/share/vm/oops/instanceKlass.cpp --- a/hotspot/src/share/vm/oops/instanceKlass.cpp Fri Jun 19 07:33:25 2009 -0700 +++ b/hotspot/src/share/vm/oops/instanceKlass.cpp Fri Jul 10 11:10:00 2009 -0700 @@ -158,9 +158,6 @@ // timer handles recursion assert(THREAD->is_Java_thread(), "non-JavaThread in link_class_impl"); JavaThread* jt = (JavaThread*)THREAD; - PerfTraceTimedEvent vmtimer(ClassLoader::perf_class_link_time(), - ClassLoader::perf_classes_linked(), - jt->get_thread_stat()->class_link_recursion_count_addr()); // link super class before linking this class instanceKlassHandle super(THREAD, this_oop->super()); @@ -194,6 +191,15 @@ return true; } + // trace only the link time for this klass that includes + // the verification time + PerfClassTraceTime vmtimer(ClassLoader::perf_class_link_time(), + ClassLoader::perf_class_link_selftime(), + ClassLoader::perf_classes_linked(), + jt->get_thread_stat()->perf_recursion_counts_addr(), + jt->get_thread_stat()->perf_timers_addr(), + PerfClassTraceTime::CLASS_LINK); + // verification & rewriting { ObjectLocker ol(this_oop, THREAD); @@ -203,12 +209,14 @@ if (!this_oop->is_linked()) { if (!this_oop->is_rewritten()) { { - assert(THREAD->is_Java_thread(), "non-JavaThread in link_class_impl"); - JavaThread* jt = (JavaThread*)THREAD; // Timer includes any side effects of class verification (resolution, // etc), but not recursive entry into verify_code(). - PerfTraceTime timer(ClassLoader::perf_class_verify_time(), - jt->get_thread_stat()->class_verify_recursion_count_addr()); + PerfClassTraceTime timer(ClassLoader::perf_class_verify_time(), + ClassLoader::perf_class_verify_selftime(), + ClassLoader::perf_classes_verified(), + jt->get_thread_stat()->perf_recursion_counts_addr(), + jt->get_thread_stat()->perf_timers_addr(), + PerfClassTraceTime::CLASS_VERIFY); bool verify_ok = verify_code(this_oop, throw_verifyerror, THREAD); if (!verify_ok) { return false; @@ -350,9 +358,12 @@ JavaThread* jt = (JavaThread*)THREAD; // Timer includes any side effects of class initialization (resolution, // etc), but not recursive entry into call_class_initializer(). - PerfTraceTimedEvent timer(ClassLoader::perf_class_init_time(), - ClassLoader::perf_classes_inited(), - jt->get_thread_stat()->class_init_recursion_count_addr()); + PerfClassTraceTime timer(ClassLoader::perf_class_init_time(), + ClassLoader::perf_class_init_selftime(), + ClassLoader::perf_classes_inited(), + jt->get_thread_stat()->perf_recursion_counts_addr(), + jt->get_thread_stat()->perf_timers_addr(), + PerfClassTraceTime::CLASS_CLINIT); this_oop->call_class_initializer(THREAD); } diff -r 9b4390b8c6f7 -r 224791e7ecab hotspot/src/share/vm/prims/jvm.cpp --- a/hotspot/src/share/vm/prims/jvm.cpp Fri Jun 19 07:33:25 2009 -0700 +++ b/hotspot/src/share/vm/prims/jvm.cpp Fri Jul 10 11:10:00 2009 -0700 @@ -756,6 +756,20 @@ static jclass jvm_define_class_common(JNIEnv *env, const char *name, jobject loader, const jbyte *buf, jsize len, jobject pd, const char *source, TRAPS) { if (source == NULL) source = "__JVM_DefineClass__"; + assert(THREAD->is_Java_thread(), "must be a JavaThread"); + JavaThread* jt = (JavaThread*) THREAD; + + PerfClassTraceTime vmtimer(ClassLoader::perf_define_appclass_time(), + ClassLoader::perf_define_appclass_selftime(), + ClassLoader::perf_define_appclasses(), + jt->get_thread_stat()->perf_recursion_counts_addr(), + jt->get_thread_stat()->perf_timers_addr(), + PerfClassTraceTime::DEFINE_CLASS); + + if (UsePerfData) { + ClassLoader::perf_app_classfile_bytes_read()->inc(len); + } + // Since exceptions can be thrown, class initialization can take place // if name is NULL no check for class name in .class stream has to be made. symbolHandle class_name; diff -r 9b4390b8c6f7 -r 224791e7ecab hotspot/src/share/vm/runtime/perfData.hpp --- a/hotspot/src/share/vm/runtime/perfData.hpp Fri Jun 19 07:33:25 2009 -0700 +++ b/hotspot/src/share/vm/runtime/perfData.hpp Fri Jul 10 11:10:00 2009 -0700 @@ -868,6 +868,10 @@ {counter = PerfDataManager::create_counter(counter_ns, counter_name, \ PerfData::U_Events,CHECK);} +#define NEWPERFBYTECOUNTER(counter, counter_ns, counter_name) \ + {counter = PerfDataManager::create_counter(counter_ns, counter_name, \ + PerfData::U_Bytes,CHECK);} + // Utility Classes /* diff -r 9b4390b8c6f7 -r 224791e7ecab hotspot/src/share/vm/services/threadService.cpp --- a/hotspot/src/share/vm/services/threadService.cpp Fri Jun 19 07:33:25 2009 -0700 +++ b/hotspot/src/share/vm/services/threadService.cpp Fri Jul 10 11:10:00 2009 -0700 @@ -688,10 +688,9 @@ _contended_enter_count = 0; _monitor_wait_count = 0; _sleep_count = 0; - _class_init_recursion_count = 0; - _class_verify_recursion_count = 0; _count_pending_reset = false; _timer_pending_reset = false; + memset((void*) _perf_recursion_counts, 0, sizeof(_perf_recursion_counts)); } ThreadSnapshot::ThreadSnapshot(JavaThread* thread) { diff -r 9b4390b8c6f7 -r 224791e7ecab hotspot/src/share/vm/services/threadService.hpp --- a/hotspot/src/share/vm/services/threadService.hpp Fri Jun 19 07:33:25 2009 -0700 +++ b/hotspot/src/share/vm/services/threadService.hpp Fri Jul 10 11:10:00 2009 -0700 @@ -120,9 +120,8 @@ bool _timer_pending_reset; // Keep accurate times for potentially recursive class operations - int _class_init_recursion_count; - int _class_verify_recursion_count; - int _class_link_recursion_count; + int _perf_recursion_counts[6]; + elapsedTimer _perf_timers[6]; // utility functions void check_and_reset_count() { @@ -165,9 +164,8 @@ void reset_count_stat() { _count_pending_reset = true; } void reset_time_stat() { _timer_pending_reset = true; } - int* class_init_recursion_count_addr() { return &_class_init_recursion_count; } - int* class_verify_recursion_count_addr() { return &_class_verify_recursion_count; } - int* class_link_recursion_count_addr() { return &_class_link_recursion_count; } + int* perf_recursion_counts_addr() { return _perf_recursion_counts; } + elapsedTimer* perf_timers_addr() { return _perf_timers; } }; // Thread snapshot to represent the thread state and statistics