comparison src/share/vm/prims/jvmtiImpl.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.
30 #include "oops/instanceKlass.hpp" 30 #include "oops/instanceKlass.hpp"
31 #include "prims/jvmtiAgentThread.hpp" 31 #include "prims/jvmtiAgentThread.hpp"
32 #include "prims/jvmtiEventController.inline.hpp" 32 #include "prims/jvmtiEventController.inline.hpp"
33 #include "prims/jvmtiImpl.hpp" 33 #include "prims/jvmtiImpl.hpp"
34 #include "prims/jvmtiRedefineClasses.hpp" 34 #include "prims/jvmtiRedefineClasses.hpp"
35 #include "runtime/atomic.hpp"
35 #include "runtime/deoptimization.hpp" 36 #include "runtime/deoptimization.hpp"
36 #include "runtime/handles.hpp" 37 #include "runtime/handles.hpp"
37 #include "runtime/handles.inline.hpp" 38 #include "runtime/handles.inline.hpp"
38 #include "runtime/interfaceSupport.hpp" 39 #include "runtime/interfaceSupport.hpp"
39 #include "runtime/javaCalls.hpp" 40 #include "runtime/javaCalls.hpp"
41 #include "runtime/serviceThread.hpp"
40 #include "runtime/signature.hpp" 42 #include "runtime/signature.hpp"
41 #include "runtime/vframe.hpp" 43 #include "runtime/vframe.hpp"
42 #include "runtime/vframe_hp.hpp" 44 #include "runtime/vframe_hp.hpp"
43 #include "runtime/vm_operations.hpp" 45 #include "runtime/vm_operations.hpp"
44 #include "utilities/exceptions.hpp" 46 #include "utilities/exceptions.hpp"
908 tty->print(") "); 910 tty->print(") ");
909 } 911 }
910 tty->print_cr("]"); 912 tty->print_cr("]");
911 #endif 913 #endif
912 } 914 }
915
916 #ifndef KERNEL
917
918 JvmtiDeferredEvent JvmtiDeferredEvent::compiled_method_load_event(
919 nmethod* nm) {
920 JvmtiDeferredEvent event = JvmtiDeferredEvent(TYPE_COMPILED_METHOD_LOAD);
921 event.set_compiled_method_load(nm);
922 nmethodLocker::lock_nmethod(nm); // will be unlocked when posted
923 return event;
924 }
925
926 JvmtiDeferredEvent JvmtiDeferredEvent::compiled_method_unload_event(
927 jmethodID id, const void* code) {
928 JvmtiDeferredEvent event = JvmtiDeferredEvent(TYPE_COMPILED_METHOD_UNLOAD);
929 event.set_compiled_method_unload(id, code);
930 return event;
931 }
932
933 void JvmtiDeferredEvent::post() {
934 switch(_type) {
935 case TYPE_COMPILED_METHOD_LOAD:
936 JvmtiExport::post_compiled_method_load(compiled_method_load());
937 nmethodLocker::unlock_nmethod(compiled_method_load());
938 break;
939 case TYPE_COMPILED_METHOD_UNLOAD:
940 JvmtiExport::post_compiled_method_unload(
941 compiled_method_unload_method_id(),
942 compiled_method_unload_code_begin());
943 break;
944 case TYPE_FLUSH:
945 JvmtiDeferredEventQueue::flush_complete(flush_state_addr());
946 break;
947 default:
948 ShouldNotReachHere();
949 }
950 }
951
952 JvmtiDeferredEventQueue::QueueNode* JvmtiDeferredEventQueue::_queue_tail = NULL;
953 JvmtiDeferredEventQueue::QueueNode* JvmtiDeferredEventQueue::_queue_head = NULL;
954
955 volatile JvmtiDeferredEventQueue::QueueNode*
956 JvmtiDeferredEventQueue::_pending_list = NULL;
957
958 bool JvmtiDeferredEventQueue::has_events() {
959 assert(Service_lock->owned_by_self(), "Must own Service_lock");
960 return _queue_head != NULL || _pending_list != NULL;
961 }
962
963 void JvmtiDeferredEventQueue::enqueue(const JvmtiDeferredEvent& event) {
964 assert(Service_lock->owned_by_self(), "Must own Service_lock");
965
966 process_pending_events();
967
968 // Events get added to the end of the queue (and are pulled off the front).
969 QueueNode* node = new QueueNode(event);
970 if (_queue_tail == NULL) {
971 _queue_tail = _queue_head = node;
972 } else {
973 assert(_queue_tail->next() == NULL, "Must be the last element in the list");
974 _queue_tail->set_next(node);
975 _queue_tail = node;
976 }
977
978 Service_lock->notify_all();
979 assert((_queue_head == NULL) == (_queue_tail == NULL),
980 "Inconsistent queue markers");
981 }
982
983 JvmtiDeferredEvent JvmtiDeferredEventQueue::dequeue() {
984 assert(Service_lock->owned_by_self(), "Must own Service_lock");
985
986 process_pending_events();
987
988 assert(_queue_head != NULL, "Nothing to dequeue");
989
990 if (_queue_head == NULL) {
991 // Just in case this happens in product; it shouldn't but let's not crash
992 return JvmtiDeferredEvent();
993 }
994
995 QueueNode* node = _queue_head;
996 _queue_head = _queue_head->next();
997 if (_queue_head == NULL) {
998 _queue_tail = NULL;
999 }
1000
1001 assert((_queue_head == NULL) == (_queue_tail == NULL),
1002 "Inconsistent queue markers");
1003
1004 JvmtiDeferredEvent event = node->event();
1005 delete node;
1006 return event;
1007 }
1008
1009 void JvmtiDeferredEventQueue::add_pending_event(
1010 const JvmtiDeferredEvent& event) {
1011
1012 QueueNode* node = new QueueNode(event);
1013
1014 bool success = false;
1015 QueueNode* prev_value = (QueueNode*)_pending_list;
1016 do {
1017 node->set_next(prev_value);
1018 prev_value = (QueueNode*)Atomic::cmpxchg_ptr(
1019 (void*)node, (volatile void*)&_pending_list, (void*)node->next());
1020 } while (prev_value != node->next());
1021 }
1022
1023 // This method transfers any events that were added by someone NOT holding
1024 // the lock into the mainline queue.
1025 void JvmtiDeferredEventQueue::process_pending_events() {
1026 assert(Service_lock->owned_by_self(), "Must own Service_lock");
1027
1028 if (_pending_list != NULL) {
1029 QueueNode* head =
1030 (QueueNode*)Atomic::xchg_ptr(NULL, (volatile void*)&_pending_list);
1031
1032 assert((_queue_head == NULL) == (_queue_tail == NULL),
1033 "Inconsistent queue markers");
1034
1035 if (head != NULL) {
1036 // Since we've treated the pending list as a stack (with newer
1037 // events at the beginning), we need to join the bottom of the stack
1038 // with the 'tail' of the queue in order to get the events in the
1039 // right order. We do this by reversing the pending list and appending
1040 // it to the queue.
1041
1042 QueueNode* new_tail = head;
1043 QueueNode* new_head = NULL;
1044
1045 // This reverses the list
1046 QueueNode* prev = new_tail;
1047 QueueNode* node = new_tail->next();
1048 new_tail->set_next(NULL);
1049 while (node != NULL) {
1050 QueueNode* next = node->next();
1051 node->set_next(prev);
1052 prev = node;
1053 node = next;
1054 }
1055 new_head = prev;
1056
1057 // Now append the new list to the queue
1058 if (_queue_tail != NULL) {
1059 _queue_tail->set_next(new_head);
1060 } else { // _queue_head == NULL
1061 _queue_head = new_head;
1062 }
1063 _queue_tail = new_tail;
1064 }
1065 }
1066 }
1067
1068 enum {
1069 // Random - used for debugging
1070 FLUSHING = 0x50403020,
1071 FLUSHED = 0x09080706
1072 };
1073
1074 void JvmtiDeferredEventQueue::flush_queue(Thread* thread) {
1075
1076 volatile int flush_state = FLUSHING;
1077
1078 JvmtiDeferredEvent flush(JvmtiDeferredEvent::TYPE_FLUSH);
1079 flush.set_flush_state_addr((int*)&flush_state);
1080
1081 if (ServiceThread::is_service_thread(thread)) {
1082 // If we are the service thread we have to post all preceding events
1083 // Use the flush event as a token to indicate when we can stop
1084 JvmtiDeferredEvent event;
1085 {
1086 MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
1087 enqueue(flush);
1088 event = dequeue();
1089 }
1090 while (!event.is_flush_event() ||
1091 event.flush_state_addr() != &flush_state) {
1092 event.post();
1093 {
1094 MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
1095 event = dequeue();
1096 }
1097 }
1098 } else {
1099 // Wake up the service thread so it will process events. When it gets
1100 // to the flush event it will set 'flush_complete' and notify us.
1101 MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
1102 enqueue(flush);
1103 while (flush_state != FLUSHED) {
1104 assert(flush_state == FLUSHING || flush_state == FLUSHED,
1105 "only valid values for this");
1106 Service_lock->wait(Mutex::_no_safepoint_check_flag);
1107 }
1108 }
1109 }
1110
1111 void JvmtiDeferredEventQueue::flush_complete(int* state_addr) {
1112 assert(state_addr != NULL && *state_addr == FLUSHING, "must be");
1113 MutexLockerEx ml(Service_lock, Mutex::_no_safepoint_check_flag);
1114 *state_addr = FLUSHED;
1115 Service_lock->notify_all();
1116 }
1117
1118 #endif // ndef KERNEL