< prev index next >

src/hotspot/share/compiler/compileBroker.cpp

Print this page




2750   bool methodNames = !strcmp(function, "MethodNames") || allFun;
2751   bool discard = !strcmp(function, "discard") || allFun;
2752 
2753   if (out == NULL) {
2754     out = tty;
2755   }
2756 
2757   if (!(aggregate || usedSpace || freeSpace || methodCount || methodSpace || methodAge || methodNames || discard)) {
2758     out->print_cr("\n__ CodeHeapStateAnalytics: Function %s is not supported", function);
2759     out->cr();
2760     return;
2761   }
2762 
2763   ts_total.update(); // record starting point
2764 
2765   if (aggregate) {
2766     print_info(out);
2767   }
2768 
2769   // We hold the CodeHeapStateAnalytics_lock all the time, from here until we leave this function.
2770   // That prevents another thread from destroying our view on the CodeHeap.
2771   // When we request individual parts of the analysis via the jcmd interface, it is possible
2772   // that in between another thread (another jcmd user or the vm running into CodeCache OOM)
2773   // updated the aggregated data. That's a tolerable tradeoff because we can't hold a lock
2774   // across user interaction.
2775   // Acquire this lock before acquiring the CodeCache_lock.
2776   // CodeHeapStateAnalytics_lock could be held by a concurrent thread for a long time,
2777   // leading to an unnecessarily long hold time of the CodeCache_lock.


2778   ts.update(); // record starting point
2779   MutexLocker mu1(CodeHeapStateAnalytics_lock, Mutex::_no_safepoint_check_flag);
2780   out->print_cr("\n__ CodeHeapStateAnalytics lock wait took %10.3f seconds _________\n", ts.seconds());
2781 
2782   // If we serve an "allFun" call, it is beneficial to hold the CodeCache_lock
2783   // for the entire duration of aggregation and printing. That makes sure
2784   // we see a consistent picture and do not run into issues caused by
2785   // the CodeHeap being altered concurrently.
2786   Mutex* global_lock   = allFun ? CodeCache_lock : NULL;
2787   Mutex* function_lock = allFun ? NULL : CodeCache_lock;













2788   ts_global.update(); // record starting point
2789   MutexLocker mu2(global_lock, Mutex::_no_safepoint_check_flag);
2790   if (global_lock != NULL) {
2791     out->print_cr("\n__ CodeCache (global) lock wait took %10.3f seconds _________\n", ts_global.seconds());

2792     ts_global.update(); // record starting point
2793   }
2794 
2795   if (aggregate) {
2796     ts.update(); // record starting point
2797     MutexLocker mu3(function_lock, Mutex::_no_safepoint_check_flag);
2798     if (function_lock != NULL) {
2799       out->print_cr("\n__ CodeCache (function) lock wait took %10.3f seconds _________\n", ts.seconds());

2800     }
2801 
2802     ts.update(); // record starting point
2803     CodeCache::aggregate(out, granularity);
2804     if (function_lock != NULL) {
2805       out->print_cr("\n__ CodeCache (function) lock hold took %10.3f seconds _________\n", ts.seconds());
2806     }
2807   }
2808 
2809   if (usedSpace) CodeCache::print_usedSpace(out);
2810   if (freeSpace) CodeCache::print_freeSpace(out);
2811   if (methodCount) CodeCache::print_count(out);
2812   if (methodSpace) CodeCache::print_space(out);
2813   if (methodAge) CodeCache::print_age(out);
2814   if (methodNames) {
2815     // print_names() has shown to be sensitive to concurrent CodeHeap modifications.
2816     // Therefore, request  the CodeCache_lock before calling...
2817     MutexLocker mu3(function_lock, Mutex::_no_safepoint_check_flag);
2818     CodeCache::print_names(out);



2819   }
2820   if (discard) CodeCache::discard(out);
2821 
2822   if (global_lock != NULL) {
2823     out->print_cr("\n__ CodeCache (global) lock hold took %10.3f seconds _________\n", ts_global.seconds());
2824   }
2825   out->print_cr("\n__ CodeHeapStateAnalytics total duration %10.3f seconds _________\n", ts_total.seconds());
2826 }


2750   bool methodNames = !strcmp(function, "MethodNames") || allFun;
2751   bool discard = !strcmp(function, "discard") || allFun;
2752 
2753   if (out == NULL) {
2754     out = tty;
2755   }
2756 
2757   if (!(aggregate || usedSpace || freeSpace || methodCount || methodSpace || methodAge || methodNames || discard)) {
2758     out->print_cr("\n__ CodeHeapStateAnalytics: Function %s is not supported", function);
2759     out->cr();
2760     return;
2761   }
2762 
2763   ts_total.update(); // record starting point
2764 
2765   if (aggregate) {
2766     print_info(out);
2767   }
2768 
2769   // We hold the CodeHeapStateAnalytics_lock all the time, from here until we leave this function.
2770   // That prevents other threads from destroying (making inconsistent) our view on the CodeHeap.
2771   // When we request individual parts of the analysis via the jcmd interface, it is possible
2772   // that in between another thread (another jcmd user or the vm running into CodeCache OOM)
2773   // updated the aggregated data. We will then see a modified, but again consistent, view
2774   // on the CodeHeap. That's a tolerable tradeoff we have to accept because we can't hold
2775   // a lock across user interaction.
2776 
2777   // We should definitely acquire this lock before acquiring Compile_lock and CodeCache_lock.
2778   // CodeHeapStateAnalytics_lock may be held by a concurrent thread for a long time,
2779   // leading to an unnecessarily long hold time of the other locks we acquired before.
2780   ts.update(); // record starting point
2781   MutexLocker mu0(CodeHeapStateAnalytics_lock, Mutex::_safepoint_check_flag);
2782   out->print_cr("\n__ CodeHeapStateAnalytics lock wait took %10.3f seconds _________\n", ts.seconds());
2783 
2784   // Holding the CodeCache_lock protects from concurrent alterations of the CodeCache.
2785   // Unfortunately, such protection is not sufficient:
2786   // When a new nmethod is created via ciEnv::register_method(), the
2787   // Compile_lock is taken first. After some initializations,
2788   // nmethod::new_nmethod() takes over, grabbing the CodeCache_lock
2789   // immediately (after finalizing the oop references). To lock out concurrent
2790   // modifiers, we have to grab both locks as well in the described sequence.
2791   //
2792   // If we serve an "allFun" call, it is beneficial to hold CodeCache_lock and Compile_lock
2793   // for the entire duration of aggregation and printing. That makes sure we see
2794   // a consistent picture and do not run into issues caused by concurrent alterations.
2795   bool should_take_Compile_lock   = !SafepointSynchronize::is_at_safepoint() &&
2796                                     !Compile_lock->owned_by_self();
2797   bool should_take_CodeCache_lock = !SafepointSynchronize::is_at_safepoint() &&
2798                                     !CodeCache_lock->owned_by_self();
2799   Mutex*   global_lock_1   = allFun ? (should_take_Compile_lock   ? Compile_lock   : NULL) : NULL;
2800   Monitor* global_lock_2   = allFun ? (should_take_CodeCache_lock ? CodeCache_lock : NULL) : NULL;
2801   Mutex*   function_lock_1 = allFun ? NULL : (should_take_Compile_lock   ? Compile_lock    : NULL);
2802   Monitor* function_lock_2 = allFun ? NULL : (should_take_CodeCache_lock ? CodeCache_lock  : NULL);
2803   ts_global.update(); // record starting point
2804   MutexLocker mu1(global_lock_1, Mutex::_safepoint_check_flag);
2805   MutexLocker mu2(global_lock_2, Mutex::_no_safepoint_check_flag);
2806   if ((global_lock_1 != NULL) || (global_lock_2 != NULL)) {
2807     out->print_cr("\n__ Compile & CodeCache (global) lock wait took %10.3f seconds _________\n", ts_global.seconds());
2808     ts_global.update(); // record starting point
2809   }
2810 
2811   if (aggregate) {
2812     ts.update(); // record starting point
2813     MutexLocker mu11(function_lock_1, Mutex::_safepoint_check_flag);
2814     MutexLocker mu22(function_lock_2, Mutex::_no_safepoint_check_flag);
2815     if ((function_lock_1 != NULL) || (function_lock_1 != NULL)) {
2816       out->print_cr("\n__ Compile & CodeCache (function) lock wait took %10.3f seconds _________\n", ts.seconds());
2817     }
2818 
2819     ts.update(); // record starting point
2820     CodeCache::aggregate(out, granularity);
2821     if ((function_lock_1 != NULL) || (function_lock_1 != NULL)) {
2822       out->print_cr("\n__ Compile & CodeCache (function) lock hold took %10.3f seconds _________\n", ts.seconds());
2823     }
2824   }
2825 
2826   if (usedSpace) CodeCache::print_usedSpace(out);
2827   if (freeSpace) CodeCache::print_freeSpace(out);
2828   if (methodCount) CodeCache::print_count(out);
2829   if (methodSpace) CodeCache::print_space(out);
2830   if (methodAge) CodeCache::print_age(out);
2831   if (methodNames) {
2832     if (allFun) {
2833       // print_names() can only be used safely if the locks have been continuously held
2834       // since aggregation begin. That is true only for function "all".
2835       CodeCache::print_names(out);
2836     } else {
2837       out->print_cr("\nCodeHeapStateAnalytics: Function 'MethodNames' is only available as part of function 'all'");
2838     }
2839   }
2840   if (discard) CodeCache::discard(out);
2841 
2842   if ((global_lock_1 != NULL) || (global_lock_2 != NULL)) {
2843     out->print_cr("\n__ Compile & CodeCache (global) lock hold took %10.3f seconds _________\n", ts_global.seconds());
2844   }
2845   out->print_cr("\n__ CodeHeapStateAnalytics total duration %10.3f seconds _________\n", ts_total.seconds());
2846 }
< prev index next >