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   JfrCheckpointWriter writer(false, true, Thread::current());
162   ClassUnloadTypeSet class_unload_set;
163   class_unload_set.serialize(writer);
164 }
165 
166 void JfrTypeManager::create_thread_checkpoint(JavaThread* jt) {
167   assert(jt != NULL, "invariant");
168   JfrThreadConstant type_thread(jt);
169   JfrCheckpointWriter writer(false, true, jt);
170   writer.write_type(TYPE_THREAD);
171   type_thread.serialize(writer);
172   // create and install a checkpoint blob
173   jt->jfr_thread_local()->set_thread_checkpoint(writer.checkpoint_blob());
174   assert(jt->jfr_thread_local()->has_thread_checkpoint(), "invariant");
175 }
176 
177 void JfrTypeManager::write_thread_checkpoint(JavaThread* jt) {
178   assert(jt != NULL, "JavaThread is NULL!");
179   ResourceMark rm(jt);
180   if (jt->jfr_thread_local()->has_thread_checkpoint()) {
181     JfrCheckpointWriter writer(false, false, jt);
182     jt->jfr_thread_local()->thread_checkpoint()->write(writer);
183   } else {
184     JfrThreadConstant type_thread(jt);
185     JfrCheckpointWriter writer(false, true, jt);
186     writer.write_type(TYPE_THREAD);
187     type_thread.serialize(writer);
188   }
189 }
190 
191 #ifdef ASSERT
192 static void assert_not_registered_twice(JfrTypeId id, List& list) {
193   const Iterator iter(list);
194   while (iter.has_next()) {
195     assert(iter.next()->id() != id, "invariant");
196   }
197 }
198 #endif
199 
200 static bool register_type(JfrTypeId id, bool require_safepoint, bool permit_cache, JfrSerializer* serializer) {
201   assert(serializer != NULL, "invariant");
202   JfrSerializerRegistration* const registration = new JfrSerializerRegistration(id, permit_cache, serializer);
203   if (registration == NULL) {
204     delete serializer;
205     return false;
206   }
207   if (require_safepoint) {
208     assert(!safepoint_types.in_list(registration), "invariant");
209     DEBUG_ONLY(assert_not_registered_twice(id, safepoint_types);)
210     safepoint_types.prepend(registration);
211   } else {
212     assert(!types.in_list(registration), "invariant");
213     DEBUG_ONLY(assert_not_registered_twice(id, types);)
214     types.prepend(registration);
215   }
216   return true;
217 }
218 
219 bool JfrTypeManager::initialize() {
220   SerializerRegistrationGuard guard;
221 
222   // register non-safepointing type serialization
223   register_type(TYPE_FLAGVALUEORIGIN, false, true, new FlagValueOriginConstant());
224   register_type(TYPE_INFLATECAUSE, false, true, new MonitorInflateCauseConstant());
225   register_type(TYPE_GCCAUSE, false, true, new GCCauseConstant());
226   register_type(TYPE_GCNAME, false, true, new GCNameConstant());
227   register_type(TYPE_GCWHEN, false, true, new GCWhenConstant());
228   register_type(TYPE_G1HEAPREGIONTYPE, false, true, new G1HeapRegionTypeConstant());
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_G1YCTYPE, false, true, new G1YCTypeConstant());
233   register_type(TYPE_REFERENCETYPE, false, true, new ReferenceTypeConstant());
234   register_type(TYPE_NARROWOOPMODE, false, true, new NarrowOopModeConstant());
235   register_type(TYPE_COMPILERPHASETYPE, false, true, new CompilerPhaseTypeConstant());
236   register_type(TYPE_CODEBLOBTYPE, false, true, new CodeBlobTypeConstant());
237   register_type(TYPE_VMOPERATIONTYPE, false, true, new VMOperationTypeConstant());
238   register_type(TYPE_THREADSTATE, false, true, new ThreadStateConstant());
239 
240   // register safepointing type serialization
241   register_type(TYPE_THREADGROUP, true, false, new JfrThreadGroupConstant());
242   register_type(TYPE_THREAD, true, false, new JfrThreadConstantSet());
243   return true;
244 }
245 
246 // implementation for the static registration function exposed in the JfrSerializer api
247 bool JfrSerializer::register_serializer(JfrTypeId id, bool require_safepoint, bool permit_cache, JfrSerializer* serializer) {
248   SerializerRegistrationGuard guard;
249   return register_type(id, require_safepoint, permit_cache, serializer);
250 }