1 /*
  2  * Copyright (c) 2016, 2020, 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/recorder/jfrRecorder.hpp"
 31 #include "jfr/support/jfrThreadLocal.hpp"
 32 #include "jfr/utilities/jfrIterator.hpp"
 33 #include "jfr/utilities/jfrLinkedList.inline.hpp"
 34 #include "memory/resourceArea.hpp"


 35 #include "runtime/semaphore.hpp"
 36 #include "runtime/thread.inline.hpp"
 37 #include "utilities/macros.hpp"
 38 
 39 class JfrSerializerRegistration : public JfrCHeapObj {
 40  public:
 41   JfrSerializerRegistration* _next; // list support
 42  private:
 43   JfrSerializer* _serializer;
 44   mutable JfrBlobHandle _cache;
 45   JfrTypeId _id;
 46   bool _permit_cache;
 47  public:
 48   JfrSerializerRegistration(JfrTypeId id, bool permit_cache, JfrSerializer* serializer) :
 49     _next(NULL), _serializer(serializer), _cache(), _id(id), _permit_cache(permit_cache) {}
 50   ~JfrSerializerRegistration() {
 51     delete _serializer;
 52   }
 53 
 54   JfrTypeId id() const {
 55     return _id;
 56   }
 57 
 58   void on_rotation() const {
 59     _serializer->on_rotation();
 60   }
 61 
 62   void invoke(JfrCheckpointWriter& writer) const {
 63     if (_cache.valid()) {
 64       writer.increment();
 65       _cache->write(writer);
 66       return;
 67     }
 68     const JfrCheckpointContext ctx = writer.context();
 69     // serialize the type id before invoking callback
 70     writer.write_type(_id);
 71     const intptr_t start = writer.current_offset();
 72     // invoke the serializer routine
 73     _serializer->serialize(writer);
 74     if (start == writer.current_offset()) {
 75       // the serializer implementation did nothing, rewind to restore
 76       writer.set_context(ctx);
 77       return;
 78     }
 79     if (_permit_cache) {
 80       _cache = writer.copy(&ctx);
 81     }
 82   }
 83 };
 84 
 85 static void serialize_threads(JfrCheckpointWriter& writer) {
 86   JfrThreadConstantSet thread_set;
 87   writer.write_type(TYPE_THREAD);
 88   thread_set.serialize(writer);
 89 }
 90 
 91 static void serialize_thread_groups(JfrCheckpointWriter& writer) {
 92   JfrThreadGroupConstant thread_group_set;
 93   writer.write_type(TYPE_THREADGROUP);
 94   thread_group_set.serialize(writer);
 95 }
 96 
 97 void JfrTypeManager::write_threads(JfrCheckpointWriter& writer) {
 98   serialize_threads(writer);
 99   serialize_thread_groups(writer);
100 }
101 
102 JfrBlobHandle JfrTypeManager::create_thread_blob(JavaThread* jt, traceid tid, oop vthread) {
103   assert(jt != NULL, "invariant");
104   ResourceMark rm(jt);
105   JfrCheckpointWriter writer(jt, true, THREADS, false); // thread local lease


106   writer.write_type(TYPE_THREAD);
107   JfrThreadConstant type_thread(jt, tid, vthread);
108   type_thread.serialize(writer);
109   return writer.move();


110 }
111 
112 void JfrTypeManager::write_checkpoint(Thread* t, traceid tid, oop vthread) {
113   assert(t != NULL, "invariant");
114   Thread* const current = Thread::current(); // not necessarily the same as t
115   assert(current != NULL, "invariant");
116   ResourceMark rm(current);
117   JfrCheckpointWriter writer(current, true, THREADS, !current->is_Java_thread());
118   writer.write_type(TYPE_THREAD);
119   JfrThreadConstant type_thread(t, tid, vthread);
120   type_thread.serialize(writer);
121 }
122 
123 class SerializerRegistrationGuard : public StackObj {
124  private:
125   static Semaphore _mutex_semaphore;
126  public:
127   SerializerRegistrationGuard() {
128     _mutex_semaphore.wait();
129   }
130   ~SerializerRegistrationGuard() {
131     _mutex_semaphore.signal();
132   }
133 };
134 
135 Semaphore SerializerRegistrationGuard::_mutex_semaphore(1);
136 
137 typedef JfrLinkedList<JfrSerializerRegistration> List;
138 static List types;
139 
140 void JfrTypeManager::destroy() {
141   SerializerRegistrationGuard guard;
142   JfrSerializerRegistration* registration;
143   while (types.is_nonempty()) {
144     registration = types.remove();
145     assert(registration != NULL, "invariant");
146     delete registration;
147   }
148 }
149 
150 class InvokeOnRotation {
151  public:
152   bool process(const JfrSerializerRegistration* r) {
153     assert(r != NULL, "invariant");
154     r->on_rotation();
155     return true;
156   }
157 };
158 
159 void JfrTypeManager::on_rotation() {
160   InvokeOnRotation ior;
161   types.iterate(ior);
162 }
163 
164 #ifdef ASSERT
165 
166 class Diversity {
167  private:
168   const JfrTypeId _id;
169  public:
170   Diversity(JfrTypeId id) : _id(id) {}
171   bool process(const JfrSerializerRegistration* r) {
172     assert(r != NULL, "invariant");
173     assert(r->id() != _id, "invariant");
174     return true;
175   }
176 };
177 
178 static void assert_not_registered_twice(JfrTypeId id, List& list) {
179   Diversity d(id);
180   types.iterate(d);
181 }
182 #endif
183 
184 static bool register_static_type(JfrTypeId id, bool permit_cache, JfrSerializer* serializer) {
185   assert(serializer != NULL, "invariant");
186   JfrSerializerRegistration* const registration = new JfrSerializerRegistration(id, permit_cache, serializer);
187   if (registration == NULL) {
188     delete serializer;
189     return false;
190   }
191   assert(!types.in_list(registration), "invariant");
192   DEBUG_ONLY(assert_not_registered_twice(id, types);)
193   if (JfrRecorder::is_recording()) {
194     JfrCheckpointWriter writer(STATICS);
195     registration->invoke(writer);
196   }
197   types.add(registration);
198   return true;
199 }
200 
201 bool JfrTypeManager::initialize() {
202   SerializerRegistrationGuard guard;
203   register_static_type(TYPE_FLAGVALUEORIGIN, true, new FlagValueOriginConstant());
204   register_static_type(TYPE_INFLATECAUSE, true, new MonitorInflateCauseConstant());
205   register_static_type(TYPE_GCCAUSE, true, new GCCauseConstant());
206   register_static_type(TYPE_GCNAME, true, new GCNameConstant());
207   register_static_type(TYPE_GCWHEN, true, new GCWhenConstant());
208   register_static_type(TYPE_GCTHRESHOLDUPDATER, true, new GCThresholdUpdaterConstant());
209   register_static_type(TYPE_METADATATYPE, true, new MetadataTypeConstant());
210   register_static_type(TYPE_METASPACEOBJECTTYPE, true, new MetaspaceObjectTypeConstant());
211   register_static_type(TYPE_REFERENCETYPE, true, new ReferenceTypeConstant());
212   register_static_type(TYPE_NARROWOOPMODE, true, new NarrowOopModeConstant());
213   register_static_type(TYPE_CODEBLOBTYPE, true, new CodeBlobTypeConstant());
214   register_static_type(TYPE_VMOPERATIONTYPE, true, new VMOperationTypeConstant());
215   register_static_type(TYPE_THREADSTATE, true, new ThreadStateConstant());
216   register_static_type(TYPE_BYTECODE, true, new BytecodeConstant());
217   register_static_type(TYPE_COMPILERTYPE, true, new CompilerTypeConstant());
218   return true;
219 }
220 
221 // implementation for the static registration function exposed in the JfrSerializer api
222 bool JfrSerializer::register_serializer(JfrTypeId id, bool permit_cache, JfrSerializer* serializer) {
223   SerializerRegistrationGuard guard;
224   return register_static_type(id, permit_cache, serializer);
225 }
226 
227 class InvokeSerializer {
228  private:
229    JfrCheckpointWriter& _writer;
230  public:
231   InvokeSerializer(JfrCheckpointWriter& writer) : _writer(writer) {}
232   bool process(const JfrSerializerRegistration* r) {
233     assert(r != NULL, "invariant");
234     r->invoke(_writer);
235     return true;
236   }
237 };
238 
239 void JfrTypeManager::write_static_types(JfrCheckpointWriter& writer) {
240   InvokeSerializer is(writer);
241   SerializerRegistrationGuard guard;
242   types.iterate(is);
243 }
--- EOF ---