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 } |