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/metadata/jfrSerializer.hpp"
  27 #include "jfr/recorder/checkpoint/jfrCheckpointWriter.hpp"
  28 #include "jfr/recorder/checkpoint/types/jfrType.hpp"
  29 #include "jfr/recorder/checkpoint/types/jfrTypeManager.hpp"
  30 #include "jfr/utilities/jfrDoublyLinkedList.hpp"
  31 #include "jfr/utilities/jfrIterator.hpp"
  32 #include "runtime/safepoint.hpp"
  33 #include "runtime/thread.inline.hpp"
  34 #include "utilities/exceptions.hpp"
  35 #include "runtime/semaphore.hpp"
  36 
  37 class JfrSerializerRegistration : public JfrCHeapObj {
  38  private:
  39   JfrSerializerRegistration* _next;
  40   JfrSerializerRegistration* _prev;
  41   JfrSerializer* _serializer;
  42   mutable JfrCheckpointBlobHandle _cache;
  43   JfrTypeId _id;
  44   bool _permit_cache;
  45 
  46  public:
  47   JfrSerializerRegistration(JfrTypeId id, bool permit_cache, JfrSerializer* serializer) :
  48     _next(NULL), _prev(NULL), _serializer(serializer), _cache(), _id(id), _permit_cache(permit_cache) {}
  49 
  50   ~JfrSerializerRegistration() {
  51     delete _serializer;
  52   }
  53 
  54   JfrSerializerRegistration* next() const {
  55     return _next;
  56   }
  57 
  58   void set_next(JfrSerializerRegistration* next) {
  59     _next = next;
  60   }
  61 
  62   JfrSerializerRegistration* prev() const {
  63     return _prev;
  64   }
  65 
  66   void set_prev(JfrSerializerRegistration* prev) {
  67     _prev = prev;
  68   }
  69 
  70   JfrTypeId id() const {
  71     return _id;
  72   }
  73 
  74   void invoke(JfrCheckpointWriter& writer) const;
  75 };
  76 
  77 void JfrSerializerRegistration::invoke(JfrCheckpointWriter& writer) const {
  78   if (_cache.valid()) {
  79     writer.increment();
  80     _cache->write(writer);
  81     return;
  82   }
  83   const JfrCheckpointContext ctx = writer.context();
  84   // serialize the type id before invoking callback
  85   writer.write_type(_id);
  86   const intptr_t start = writer.current_offset();
  87   // invoke the serializer routine
  88   _serializer->serialize(writer);
  89   if (start == writer.current_offset() ) {
  90     // the serializer implementation did nothing, rewind to restore
  91     writer.set_context(ctx);
  92     return;
  93   }
  94   if (_permit_cache) {
  95     _cache = writer.copy(&ctx);
  96   }
  97 }
  98 
  99 class SerializerRegistrationGuard : public StackObj {
 100  private:
 101   static Semaphore _mutex_semaphore;
 102  public:
 103   SerializerRegistrationGuard() {
 104     _mutex_semaphore.wait();
 105   }
 106   ~SerializerRegistrationGuard() {
 107     _mutex_semaphore.signal();
 108   }
 109 };
 110 
 111 Semaphore SerializerRegistrationGuard::_mutex_semaphore(1);
 112 
 113 typedef JfrDoublyLinkedList<JfrSerializerRegistration> List;
 114 typedef StopOnNullIterator<const List> Iterator;
 115 static List types;
 116 static List safepoint_types;
 117 
 118 void JfrTypeManager::clear() {
 119   SerializerRegistrationGuard guard;
 120   Iterator iter(types);
 121   JfrSerializerRegistration* registration;
 122   while (iter.has_next()) {
 123     registration = types.remove(iter.next());
 124     assert(registration != NULL, "invariant");
 125     delete registration;
 126   }
 127   Iterator sp_type_iter(safepoint_types);
 128   while (sp_type_iter.has_next()) {
 129     registration = safepoint_types.remove(sp_type_iter.next());
 130     assert(registration != NULL, "invariant");
 131     delete registration;
 132   }
 133 }
 134 
 135 void JfrTypeManager::write_types(JfrCheckpointWriter& writer) {
 136   const Iterator iter(types);
 137   while (iter.has_next()) {
 138     iter.next()->invoke(writer);
 139   }
 140 }
 141 
 142 void JfrTypeManager::write_safepoint_types(JfrCheckpointWriter& writer) {
 143   assert(SafepointSynchronize::is_at_safepoint(), "invariant");
 144   const Iterator iter(safepoint_types);
 145   while (iter.has_next()) {
 146     iter.next()->invoke(writer);
 147   }
 148 }
 149 
 150 void JfrTypeManager::write_type_set() {
 151   // can safepoint here because of Module_lock
 152   MutexLocker cld_lock(SafepointSynchronize::is_at_safepoint() ? NULL : ClassLoaderDataGraph_lock);
 153   MutexLocker lock(SafepointSynchronize::is_at_safepoint() ? NULL : Module_lock);
 154 
 155   JfrCheckpointWriter writer(true, true, Thread::current());
 156   TypeSet set;
 157   set.serialize(writer);
 158 }
 159 
 160 void JfrTypeManager::write_type_set_for_unloaded_classes() {
 161   assert_locked_or_safepoint(ClassLoaderDataGraph_lock);
 162   JfrCheckpointWriter writer(false, true, Thread::current());
 163   ClassUnloadTypeSet class_unload_set;
 164   class_unload_set.serialize(writer);
 165 }
 166 
 167 void JfrTypeManager::create_thread_checkpoint(JavaThread* jt) {
 168   assert(jt != NULL, "invariant");
 169   JfrThreadConstant type_thread(jt);
 170   JfrCheckpointWriter writer(false, true, jt);
 171   writer.write_type(TYPE_THREAD);
 172   type_thread.serialize(writer);
 173   // create and install a checkpoint blob
 174   jt->jfr_thread_local()->set_thread_checkpoint(writer.checkpoint_blob());
 175   assert(jt->jfr_thread_local()->has_thread_checkpoint(), "invariant");
 176 }
 177 
 178 void JfrTypeManager::write_thread_checkpoint(JavaThread* jt) {
 179   assert(jt != NULL, "JavaThread is NULL!");
 180   ResourceMark rm(jt);
 181   if (jt->jfr_thread_local()->has_thread_checkpoint()) {
 182     JfrCheckpointWriter writer(false, false, jt);
 183     jt->jfr_thread_local()->thread_checkpoint()->write(writer);
 184   } else {
 185     JfrThreadConstant type_thread(jt);
 186     JfrCheckpointWriter writer(false, true, jt);
 187     writer.write_type(TYPE_THREAD);
 188     type_thread.serialize(writer);
 189   }
 190 }
 191 
 192 #ifdef ASSERT
 193 static void assert_not_registered_twice(JfrTypeId id, List& list) {
 194   const Iterator iter(list);
 195   while (iter.has_next()) {
 196     assert(iter.next()->id() != id, "invariant");
 197   }
 198 }
 199 #endif
 200 
 201 static bool register_type(JfrTypeId id, bool require_safepoint, bool permit_cache, JfrSerializer* serializer) {
 202   assert(serializer != NULL, "invariant");
 203   JfrSerializerRegistration* const registration = new JfrSerializerRegistration(id, permit_cache, serializer);
 204   if (registration == NULL) {
 205     delete serializer;
 206     return false;
 207   }
 208   if (require_safepoint) {
 209     assert(!safepoint_types.in_list(registration), "invariant");
 210     DEBUG_ONLY(assert_not_registered_twice(id, safepoint_types);)
 211     safepoint_types.prepend(registration);
 212   } else {
 213     assert(!types.in_list(registration), "invariant");
 214     DEBUG_ONLY(assert_not_registered_twice(id, types);)
 215     types.prepend(registration);
 216   }
 217   return true;
 218 }
 219 
 220 bool JfrTypeManager::initialize() {
 221   SerializerRegistrationGuard guard;
 222 
 223   // register non-safepointing type serialization
 224   register_type(TYPE_FLAGVALUEORIGIN, false, true, new FlagValueOriginConstant());
 225   register_type(TYPE_INFLATECAUSE, false, true, new MonitorInflateCauseConstant());
 226   register_type(TYPE_GCCAUSE, false, true, new GCCauseConstant());
 227   register_type(TYPE_GCNAME, false, true, new GCNameConstant());
 228   register_type(TYPE_GCWHEN, false, true, new GCWhenConstant());
 229   register_type(TYPE_GCTHRESHOLDUPDATER, false, true, new GCThresholdUpdaterConstant());
 230   register_type(TYPE_METADATATYPE, false, true, new MetadataTypeConstant());
 231   register_type(TYPE_METASPACEOBJECTTYPE, false, true, new MetaspaceObjectTypeConstant());
 232   register_type(TYPE_REFERENCETYPE, false, true, new ReferenceTypeConstant());
 233   register_type(TYPE_NARROWOOPMODE, false, true, new NarrowOopModeConstant());
 234   register_type(TYPE_COMPILERPHASETYPE, false, true, new CompilerPhaseTypeConstant());
 235   register_type(TYPE_CODEBLOBTYPE, false, true, new CodeBlobTypeConstant());
 236   register_type(TYPE_VMOPERATIONTYPE, false, true, new VMOperationTypeConstant());
 237   register_type(TYPE_THREADSTATE, false, true, new ThreadStateConstant());
 238 
 239   // register safepointing type serialization
 240   register_type(TYPE_THREADGROUP, true, false, new JfrThreadGroupConstant());
 241   register_type(TYPE_THREAD, true, false, new JfrThreadConstantSet());
 242   return true;
 243 }
 244 
 245 // implementation for the static registration function exposed in the JfrSerializer api
 246 bool JfrSerializer::register_serializer(JfrTypeId id, bool require_safepoint, bool permit_cache, JfrSerializer* serializer) {
 247   SerializerRegistrationGuard guard;
 248   return register_type(id, require_safepoint, permit_cache, serializer);
 249 }