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 }