comparison src/share/vm/prims/jvmtiExport.cpp @ 2195:bf8517f4e4d0

6766644: Redefinition of compiled method fails with assertion "Can not load classes with the Compiler thread" Summary: Defer posting events from the compiler thread: use service thread Reviewed-by: coleenp, dholmes, never, dcubed
author kamg
date Wed, 02 Feb 2011 14:38:01 -0500
parents 3582bf76420e
children f91db74a6810
comparison
equal deleted inserted replaced
2194:face83fc8882 2195:bf8517f4e4d0
1 /* 1 /*
2 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. 2 * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 * 4 *
5 * This code is free software; you can redistribute it and/or modify it 5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as 6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation. 7 * published by the Free Software Foundation.
748 /////////////////////////////////////////////////////////////// 748 ///////////////////////////////////////////////////////////////
749 // 749 //
750 // pending CompiledMethodUnload support 750 // pending CompiledMethodUnload support
751 // 751 //
752 752
753 bool JvmtiExport::_have_pending_compiled_method_unload_events; 753 void JvmtiExport::post_compiled_method_unload(
754 GrowableArray<jmethodID>* JvmtiExport::_pending_compiled_method_unload_method_ids; 754 jmethodID method, const void *code_begin) {
755 GrowableArray<const void *>* JvmtiExport::_pending_compiled_method_unload_code_begins; 755 JavaThread* thread = JavaThread::current();
756 JavaThread* JvmtiExport::_current_poster;
757
758 void JvmtiExport::post_compiled_method_unload_internal(JavaThread* self, jmethodID method, const void *code_begin) {
759 EVT_TRIG_TRACE(JVMTI_EVENT_COMPILED_METHOD_UNLOAD, 756 EVT_TRIG_TRACE(JVMTI_EVENT_COMPILED_METHOD_UNLOAD,
760 ("JVMTI [%s] method compile unload event triggered", 757 ("JVMTI [%s] method compile unload event triggered",
761 JvmtiTrace::safe_get_thread_name(self))); 758 JvmtiTrace::safe_get_thread_name(thread)));
762 759
763 // post the event for each environment that has this event enabled. 760 // post the event for each environment that has this event enabled.
764 JvmtiEnvIterator it; 761 JvmtiEnvIterator it;
765 for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) { 762 for (JvmtiEnv* env = it.first(); env != NULL; env = it.next(env)) {
766 if (env->is_enabled(JVMTI_EVENT_COMPILED_METHOD_UNLOAD)) { 763 if (env->is_enabled(JVMTI_EVENT_COMPILED_METHOD_UNLOAD)) {
767 764
768 EVT_TRACE(JVMTI_EVENT_COMPILED_METHOD_UNLOAD, 765 EVT_TRACE(JVMTI_EVENT_COMPILED_METHOD_UNLOAD,
769 ("JVMTI [%s] class compile method unload event sent jmethodID " PTR_FORMAT, 766 ("JVMTI [%s] class compile method unload event sent jmethodID " PTR_FORMAT,
770 JvmtiTrace::safe_get_thread_name(self), method)); 767 JvmtiTrace::safe_get_thread_name(thread), method));
771 768
772 ResourceMark rm(self); 769 ResourceMark rm(thread);
773 770
774 JvmtiEventMark jem(self); 771 JvmtiEventMark jem(thread);
775 JvmtiJavaThreadEventTransition jet(self); 772 JvmtiJavaThreadEventTransition jet(thread);
776 jvmtiEventCompiledMethodUnload callback = env->callbacks()->CompiledMethodUnload; 773 jvmtiEventCompiledMethodUnload callback = env->callbacks()->CompiledMethodUnload;
777 if (callback != NULL) { 774 if (callback != NULL) {
778 (*callback)(env->jvmti_external(), method, code_begin); 775 (*callback)(env->jvmti_external(), method, code_begin);
779 } 776 }
780 }
781 }
782 }
783
784 // post any pending CompiledMethodUnload events
785
786 void JvmtiExport::post_pending_compiled_method_unload_events() {
787 JavaThread* self = JavaThread::current();
788 assert(!self->owns_locks(), "can't hold locks");
789
790 // Indicates if this is the first activiation of this function.
791 // In theory the profiler's callback could call back into VM and provoke
792 // another CompiledMethodLoad event to be posted from this thread. As the
793 // stack rewinds we need to ensure that the original activation does the
794 // completion and notifies any waiters.
795 bool first_activation = false;
796
797 // the jmethodID (may not be valid) to be used for a single event
798 jmethodID method;
799 const void *code_begin;
800
801 // grab the monitor and check if another thread is already posting
802 // events. If there is another thread posting events then we wait
803 // until it completes. (In theory we could check the pending events to
804 // see if any of the addresses overlap with the event that we want to
805 // post but as it will happen so rarely we just block any thread waiting
806 // to post a CompiledMethodLoad or DynamicCodeGenerated event until all
807 // pending CompiledMethodUnload events have been posted).
808 //
809 // If another thread isn't posting we examine the list of pending jmethodIDs.
810 // If the list is empty then we are done. If it's not empty then this thread
811 // (self) becomes the pending event poster and we remove the top (last)
812 // event from the list. Note that this means we remove the newest event first
813 // but as they are all CompiledMethodUnload events the order doesn't matter.
814 // Once we have removed a jmethodID then we exit the monitor. Any other thread
815 // wanting to post a CompiledMethodLoad or DynamicCodeGenerated event will
816 // be forced to wait on the monitor.
817 {
818 MutexLocker mu(JvmtiPendingEvent_lock);
819 if (_current_poster != self) {
820 while (_current_poster != NULL) {
821 JvmtiPendingEvent_lock->wait();
822 }
823 }
824 if ((_pending_compiled_method_unload_method_ids == NULL) ||
825 (_pending_compiled_method_unload_method_ids->length() == 0)) {
826 return;
827 }
828 if (_current_poster == NULL) {
829 _current_poster = self;
830 first_activation = true;
831 } else {
832 // re-entrant
833 guarantee(_current_poster == self, "checking");
834 }
835 method = _pending_compiled_method_unload_method_ids->pop();
836 code_begin = _pending_compiled_method_unload_code_begins->pop();
837 }
838
839 // This thread is the pending event poster so it first posts the CompiledMethodUnload
840 // event for the jmethodID that has been removed from the list. Once posted it
841 // re-grabs the monitor and checks the list again. If the list is empty then and this
842 // is the first activation of the function then we reset the _have_pending_events
843 // flag, cleanup _current_poster to indicate that no thread is now servicing the
844 // pending events list, and finally notify any thread that might be waiting.
845 for (;;) {
846 post_compiled_method_unload_internal(self, method, code_begin);
847
848 // event posted, now re-grab monitor and get the next event
849 // If there's no next event then we are done. If this is the first
850 // activiation of this function by this thread notify any waiters
851 // so that they can post.
852 {
853 MutexLocker ml(JvmtiPendingEvent_lock);
854 if (_pending_compiled_method_unload_method_ids->length() == 0) {
855 if (first_activation) {
856 _have_pending_compiled_method_unload_events = false;
857 _current_poster = NULL;
858 JvmtiPendingEvent_lock->notify_all();
859 }
860 return;
861 }
862 method = _pending_compiled_method_unload_method_ids->pop();
863 code_begin = _pending_compiled_method_unload_code_begins->pop();
864 } 777 }
865 } 778 }
866 } 779 }
867 780
868 /////////////////////////////////////////////////////////////// 781 ///////////////////////////////////////////////////////////////
1828 } 1741 }
1829 return record; 1742 return record;
1830 } 1743 }
1831 1744
1832 void JvmtiExport::post_compiled_method_load(nmethod *nm) { 1745 void JvmtiExport::post_compiled_method_load(nmethod *nm) {
1833 // If there are pending CompiledMethodUnload events then these are
1834 // posted before this CompiledMethodLoad event. We "lock" the nmethod and
1835 // maintain a handle to the methodOop to ensure that the nmethod isn't
1836 // flushed or unloaded while posting the events.
1837 JavaThread* thread = JavaThread::current(); 1746 JavaThread* thread = JavaThread::current();
1838 if (have_pending_compiled_method_unload_events()) {
1839 methodHandle mh(thread, nm->method());
1840 nmethodLocker nml(nm);
1841 post_pending_compiled_method_unload_events();
1842 }
1843 1747
1844 EVT_TRIG_TRACE(JVMTI_EVENT_COMPILED_METHOD_LOAD, 1748 EVT_TRIG_TRACE(JVMTI_EVENT_COMPILED_METHOD_LOAD,
1845 ("JVMTI [%s] method compile load event triggered", 1749 ("JVMTI [%s] method compile load event triggered",
1846 JvmtiTrace::safe_get_thread_name(thread))); 1750 JvmtiTrace::safe_get_thread_name(thread)));
1847 1751
1852 EVT_TRACE(JVMTI_EVENT_COMPILED_METHOD_LOAD, 1756 EVT_TRACE(JVMTI_EVENT_COMPILED_METHOD_LOAD,
1853 ("JVMTI [%s] class compile method load event sent %s.%s ", 1757 ("JVMTI [%s] class compile method load event sent %s.%s ",
1854 JvmtiTrace::safe_get_thread_name(thread), 1758 JvmtiTrace::safe_get_thread_name(thread),
1855 (nm->method() == NULL) ? "NULL" : nm->method()->klass_name()->as_C_string(), 1759 (nm->method() == NULL) ? "NULL" : nm->method()->klass_name()->as_C_string(),
1856 (nm->method() == NULL) ? "NULL" : nm->method()->name()->as_C_string())); 1760 (nm->method() == NULL) ? "NULL" : nm->method()->name()->as_C_string()));
1857
1858 ResourceMark rm(thread); 1761 ResourceMark rm(thread);
1762 HandleMark hm(thread);
1859 1763
1860 // Add inlining information 1764 // Add inlining information
1861 jvmtiCompiledMethodLoadInlineRecord* inlinerecord = create_inline_record(nm); 1765 jvmtiCompiledMethodLoadInlineRecord* inlinerecord = create_inline_record(nm);
1862 // Pass inlining information through the void pointer 1766 // Pass inlining information through the void pointer
1863 JvmtiCompiledMethodLoadEventMark jem(thread, nm, inlinerecord); 1767 JvmtiCompiledMethodLoadEventMark jem(thread, nm, inlinerecord);
1894 if (callback != NULL) { 1798 if (callback != NULL) {
1895 (*callback)(env->jvmti_external(), method, 1799 (*callback)(env->jvmti_external(), method,
1896 length, code_begin, map_length, 1800 length, code_begin, map_length,
1897 map, NULL); 1801 map, NULL);
1898 } 1802 }
1899 }
1900 }
1901
1902 // used at a safepoint to post a CompiledMethodUnload event
1903 void JvmtiExport::post_compiled_method_unload(jmethodID mid, const void *code_begin) {
1904 if (SafepointSynchronize::is_at_safepoint()) {
1905 // Class unloading can cause nmethod unloading which is reported
1906 // by the VMThread. These must be batched to be processed later.
1907 if (_pending_compiled_method_unload_method_ids == NULL) {
1908 // create list lazily
1909 _pending_compiled_method_unload_method_ids = new (ResourceObj::C_HEAP) GrowableArray<jmethodID>(10,true);
1910 _pending_compiled_method_unload_code_begins = new (ResourceObj::C_HEAP) GrowableArray<const void *>(10,true);
1911 }
1912 _pending_compiled_method_unload_method_ids->append(mid);
1913 _pending_compiled_method_unload_code_begins->append(code_begin);
1914 _have_pending_compiled_method_unload_events = true;
1915 } else {
1916 // Unloading caused by the sweeper can be reported synchronously.
1917 if (have_pending_compiled_method_unload_events()) {
1918 post_pending_compiled_method_unload_events();
1919 }
1920 post_compiled_method_unload_internal(JavaThread::current(), mid, code_begin);
1921 } 1803 }
1922 } 1804 }
1923 1805
1924 void JvmtiExport::post_dynamic_code_generated_internal(const char *name, const void *code_begin, const void *code_end) { 1806 void JvmtiExport::post_dynamic_code_generated_internal(const char *name, const void *code_begin, const void *code_end) {
1925 JavaThread* thread = JavaThread::current(); 1807 JavaThread* thread = JavaThread::current();
1951 if (phase == JVMTI_PHASE_PRIMORDIAL || phase == JVMTI_PHASE_START) { 1833 if (phase == JVMTI_PHASE_PRIMORDIAL || phase == JVMTI_PHASE_START) {
1952 post_dynamic_code_generated_internal(name, code_begin, code_end); 1834 post_dynamic_code_generated_internal(name, code_begin, code_end);
1953 return; 1835 return;
1954 } 1836 }
1955 1837
1956 if (have_pending_compiled_method_unload_events()) { 1838 // Blocks until everything now in the queue has been posted
1957 post_pending_compiled_method_unload_events(); 1839 JvmtiDeferredEventQueue::flush_queue(Thread::current());
1958 } 1840
1959 post_dynamic_code_generated_internal(name, code_begin, code_end); 1841 post_dynamic_code_generated_internal(name, code_begin, code_end);
1960 } 1842 }
1961 1843
1962 1844
1963 // post a DYNAMIC_CODE_GENERATED event for a given environment 1845 // post a DYNAMIC_CODE_GENERATED event for a given environment