1 /*
  2  * Copyright (c) 2016, 2018, 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   MutexLockerEx cld_lock(SafepointSynchronize::is_at_safepoint() ? NULL : ClassLoaderDataGraph_lock);
153   MutexLockerEx 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_G1HEAPREGIONTYPE, false, true, new G1HeapRegionTypeConstant());
230   register_type(TYPE_GCTHRESHOLDUPDATER, false, true, new GCThresholdUpdaterConstant());
231   register_type(TYPE_METADATATYPE, false, true, new MetadataTypeConstant());
232   register_type(TYPE_METASPACEOBJECTTYPE, false, true, new MetaspaceObjectTypeConstant());
233   register_type(TYPE_G1YCTYPE, false, true, new G1YCTypeConstant());
234   register_type(TYPE_REFERENCETYPE, false, true, new ReferenceTypeConstant());
235   register_type(TYPE_NARROWOOPMODE, false, true, new NarrowOopModeConstant());
236   register_type(TYPE_COMPILERPHASETYPE, false, true, new CompilerPhaseTypeConstant());
237   register_type(TYPE_CODEBLOBTYPE, false, true, new CodeBlobTypeConstant());
238   register_type(TYPE_VMOPERATIONTYPE, false, true, new VMOperationTypeConstant());
239   register_type(TYPE_THREADSTATE, false, true, new ThreadStateConstant());
240 
241   // register safepointing type serialization
242   register_type(TYPE_THREADGROUP, true, false, new JfrThreadGroupConstant());
243   register_type(TYPE_THREAD, true, false, new JfrThreadConstantSet());
244   return true;
245 }
246 
247 // implementation for the static registration function exposed in the JfrSerializer api
248 bool JfrSerializer::register_serializer(JfrTypeId id, bool require_safepoint, bool permit_cache, JfrSerializer* serializer) {
249   SerializerRegistrationGuard guard;
250   return register_type(id, require_safepoint, permit_cache, serializer);
251 }