1 /* 2 * Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 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 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 * 23 */ 24 25 #include "precompiled.hpp" 26 #include "jfr/jfr.hpp" 27 #include "jfr/leakprofiler/leakProfiler.hpp" 28 #include "jfr/leakprofiler/checkpoint/objectSampleCheckpoint.hpp" 29 #include "jfr/metadata/jfrSerializer.hpp" 30 #include "jfr/recorder/checkpoint/jfrCheckpointWriter.hpp" 31 #include "jfr/recorder/checkpoint/types/jfrType.hpp" 32 #include "jfr/recorder/checkpoint/types/jfrTypeManager.hpp" 33 #include "jfr/utilities/jfrDoublyLinkedList.hpp" 34 #include "jfr/utilities/jfrIterator.hpp" 35 #include "memory/resourceArea.hpp" 36 #include "runtime/handles.inline.hpp" 37 #include "runtime/safepoint.hpp" 38 #include "runtime/thread.inline.hpp" 39 #include "utilities/exceptions.hpp" 40 #include "runtime/semaphore.hpp" 41 42 class JfrSerializerRegistration : public JfrCHeapObj { 43 private: 44 JfrSerializerRegistration* _next; 45 JfrSerializerRegistration* _prev; 46 JfrSerializer* _serializer; 47 mutable JfrBlobHandle _cache; 48 JfrTypeId _id; 49 bool _permit_cache; 50 51 public: 52 JfrSerializerRegistration(JfrTypeId id, bool permit_cache, JfrSerializer* serializer) : 53 _next(NULL), _prev(NULL), _serializer(serializer), _cache(), _id(id), _permit_cache(permit_cache) {} 54 55 ~JfrSerializerRegistration() { 56 delete _serializer; 57 } 58 59 JfrSerializerRegistration* next() const { 60 return _next; 61 } 62 63 void set_next(JfrSerializerRegistration* next) { 64 _next = next; 65 } 66 67 JfrSerializerRegistration* prev() const { 68 return _prev; 69 } 70 71 void set_prev(JfrSerializerRegistration* prev) { 72 _prev = prev; 73 } 74 75 JfrTypeId id() const { 76 return _id; 77 } 78 79 void invoke(JfrCheckpointWriter& writer) const; 80 }; 81 82 void JfrSerializerRegistration::invoke(JfrCheckpointWriter& writer) const { 83 if (_cache.valid()) { 84 writer.increment(); 85 _cache->write(writer); 86 return; 87 } 88 const JfrCheckpointContext ctx = writer.context(); 89 // serialize the type id before invoking callback 90 writer.write_type(_id); 91 const intptr_t start = writer.current_offset(); 92 // invoke the serializer routine 93 _serializer->serialize(writer); 94 if (start == writer.current_offset() ) { 95 // the serializer implementation did nothing, rewind to restore 96 writer.set_context(ctx); 97 return; 98 } 99 if (_permit_cache) { 100 _cache = writer.copy(&ctx); 101 } 102 } 103 104 class SerializerRegistrationGuard : public StackObj { 105 private: 106 static Semaphore _mutex_semaphore; 107 public: 108 SerializerRegistrationGuard() { 109 _mutex_semaphore.wait(); 110 } 111 ~SerializerRegistrationGuard() { 112 _mutex_semaphore.signal(); 113 } 114 }; 115 116 Semaphore SerializerRegistrationGuard::_mutex_semaphore(1); 117 118 typedef JfrDoublyLinkedList<JfrSerializerRegistration> List; 119 typedef StopOnNullIterator<const List> Iterator; 120 static List types; 121 static List safepoint_types; 122 123 void JfrTypeManager::clear() { 124 SerializerRegistrationGuard guard; 125 Iterator iter(types); 126 JfrSerializerRegistration* registration; 127 while (iter.has_next()) { 128 registration = types.remove(iter.next()); 129 assert(registration != NULL, "invariant"); 130 delete registration; 131 } 132 Iterator sp_type_iter(safepoint_types); 133 while (sp_type_iter.has_next()) { 134 registration = safepoint_types.remove(sp_type_iter.next()); 135 assert(registration != NULL, "invariant"); 136 delete registration; 137 } 138 } 139 140 void JfrTypeManager::write_types(JfrCheckpointWriter& writer) { 141 const Iterator iter(types); 142 while (iter.has_next()) { 143 iter.next()->invoke(writer); 144 } 145 } 146 147 void JfrTypeManager::write_safepoint_types(JfrCheckpointWriter& writer) { 148 assert(SafepointSynchronize::is_at_safepoint(), "invariant"); 149 const Iterator iter(safepoint_types); 150 while (iter.has_next()) { 151 iter.next()->invoke(writer); 152 } 153 } 154 155 void JfrTypeManager::write_type_set() { 156 assert(!SafepointSynchronize::is_at_safepoint(), "invariant"); 157 // can safepoint here 158 MutexLocker cld_lock(ClassLoaderDataGraph_lock); 159 MutexLocker module_lock(Module_lock); 160 if (!LeakProfiler::is_running()) { 161 JfrCheckpointWriter writer(true, true, Thread::current()); 162 TypeSet set; 163 set.serialize(writer); 164 return; 165 } 166 JfrCheckpointWriter leakp_writer(false, true, Thread::current()); 167 JfrCheckpointWriter writer(false, true, Thread::current()); 168 TypeSet set(&leakp_writer); 169 set.serialize(writer); 170 ObjectSampleCheckpoint::on_type_set(leakp_writer); 171 } 172 173 void JfrTypeManager::write_type_set_for_unloaded_classes() { 174 assert_locked_or_safepoint(ClassLoaderDataGraph_lock); 175 JfrCheckpointWriter writer(false, true, Thread::current()); 176 const JfrCheckpointContext ctx = writer.context(); 177 ClassUnloadTypeSet class_unload_set; 178 class_unload_set.serialize(writer); 179 if (LeakProfiler::is_running()) { 180 ObjectSampleCheckpoint::on_type_set_unload(writer); 181 } 182 if (!Jfr::is_recording()) { 183 // discard anything written 184 writer.set_context(ctx); 185 } 186 } 187 188 void JfrTypeManager::create_thread_blob(JavaThread* jt) { 189 assert(jt != NULL, "invariant"); 190 ResourceMark rm(jt); 191 HandleMark hm(jt); 192 JfrThreadConstant type_thread(jt); 193 JfrCheckpointWriter writer(false, true, jt); 194 writer.write_type(TYPE_THREAD); 195 type_thread.serialize(writer); 196 // create and install a checkpoint blob 197 jt->jfr_thread_local()->set_thread_blob(writer.move()); 198 assert(jt->jfr_thread_local()->has_thread_blob(), "invariant"); 199 } 200 201 void JfrTypeManager::write_thread_checkpoint(JavaThread* jt) { 202 assert(jt != NULL, "JavaThread is NULL!"); 203 ResourceMark rm(jt); 204 HandleMark hm(jt); 205 JfrThreadConstant type_thread(jt); 206 JfrCheckpointWriter writer(false, true, jt); 207 writer.write_type(TYPE_THREAD); 208 type_thread.serialize(writer); 209 } 210 211 #ifdef ASSERT 212 static void assert_not_registered_twice(JfrTypeId id, List& list) { 213 const Iterator iter(list); 214 while (iter.has_next()) { 215 assert(iter.next()->id() != id, "invariant"); 216 } 217 } 218 #endif 219 220 static bool register_type(JfrTypeId id, bool require_safepoint, bool permit_cache, JfrSerializer* serializer) { 221 assert(serializer != NULL, "invariant"); 222 JfrSerializerRegistration* const registration = new JfrSerializerRegistration(id, permit_cache, serializer); 223 if (registration == NULL) { 224 delete serializer; 225 return false; 226 } 227 if (require_safepoint) { 228 assert(!safepoint_types.in_list(registration), "invariant"); 229 DEBUG_ONLY(assert_not_registered_twice(id, safepoint_types);) 230 safepoint_types.prepend(registration); 231 } else { 232 assert(!types.in_list(registration), "invariant"); 233 DEBUG_ONLY(assert_not_registered_twice(id, types);) 234 types.prepend(registration); 235 } 236 return true; 237 } 238 239 bool JfrTypeManager::initialize() { 240 SerializerRegistrationGuard guard; 241 242 // register non-safepointing type serialization 243 register_type(TYPE_FLAGVALUEORIGIN, false, true, new FlagValueOriginConstant()); 244 register_type(TYPE_INFLATECAUSE, false, true, new MonitorInflateCauseConstant()); 245 register_type(TYPE_GCCAUSE, false, true, new GCCauseConstant()); 246 register_type(TYPE_GCNAME, false, true, new GCNameConstant()); 247 register_type(TYPE_GCWHEN, false, true, new GCWhenConstant()); 248 register_type(TYPE_GCTHRESHOLDUPDATER, false, true, new GCThresholdUpdaterConstant()); 249 register_type(TYPE_METADATATYPE, false, true, new MetadataTypeConstant()); 250 register_type(TYPE_METASPACEOBJECTTYPE, false, true, new MetaspaceObjectTypeConstant()); 251 register_type(TYPE_REFERENCETYPE, false, true, new ReferenceTypeConstant()); 252 register_type(TYPE_NARROWOOPMODE, false, true, new NarrowOopModeConstant()); 253 register_type(TYPE_COMPILERPHASETYPE, false, true, new CompilerPhaseTypeConstant()); 254 register_type(TYPE_CODEBLOBTYPE, false, true, new CodeBlobTypeConstant()); 255 register_type(TYPE_VMOPERATIONTYPE, false, true, new VMOperationTypeConstant()); 256 register_type(TYPE_THREADSTATE, false, true, new ThreadStateConstant()); 257 258 // register safepointing type serialization 259 register_type(TYPE_THREADGROUP, true, false, new JfrThreadGroupConstant()); 260 register_type(TYPE_THREAD, true, false, new JfrThreadConstantSet()); 261 return true; 262 } 263 264 // implementation for the static registration function exposed in the JfrSerializer api 265 bool JfrSerializer::register_serializer(JfrTypeId id, bool require_safepoint, bool permit_cache, JfrSerializer* serializer) { 266 SerializerRegistrationGuard guard; 267 return register_type(id, require_safepoint, permit_cache, serializer); 268 }