71 |
72 |
72 JfrTypeId id() const { |
73 JfrTypeId id() const { |
73 return _id; |
74 return _id; |
74 } |
75 } |
75 |
76 |
76 void invoke(JfrCheckpointWriter& writer) const; |
77 void on_rotation() const { |
|
78 _serializer->on_rotation(); |
|
79 } |
|
80 |
|
81 void invoke(JfrCheckpointWriter& writer) const { |
|
82 if (_cache.valid()) { |
|
83 writer.increment(); |
|
84 _cache->write(writer); |
|
85 return; |
|
86 } |
|
87 const JfrCheckpointContext ctx = writer.context(); |
|
88 // serialize the type id before invoking callback |
|
89 writer.write_type(_id); |
|
90 const intptr_t start = writer.current_offset(); |
|
91 // invoke the serializer routine |
|
92 _serializer->serialize(writer); |
|
93 if (start == writer.current_offset()) { |
|
94 // the serializer implementation did nothing, rewind to restore |
|
95 writer.set_context(ctx); |
|
96 return; |
|
97 } |
|
98 if (_permit_cache) { |
|
99 _cache = writer.copy(&ctx); |
|
100 } |
|
101 } |
77 }; |
102 }; |
78 |
103 |
79 void JfrSerializerRegistration::invoke(JfrCheckpointWriter& writer) const { |
104 static void serialize_threads(JfrCheckpointWriter& writer) { |
80 if (_cache.valid()) { |
105 JfrThreadConstantSet thread_set; |
81 writer.increment(); |
106 writer.write_type(TYPE_THREAD); |
82 _cache->write(writer); |
107 thread_set.serialize(writer); |
83 return; |
108 } |
84 } |
109 |
85 const JfrCheckpointContext ctx = writer.context(); |
110 static void serialize_thread_groups(JfrCheckpointWriter& writer) { |
86 // serialize the type id before invoking callback |
111 JfrThreadGroupConstant thread_group_set; |
87 writer.write_type(_id); |
112 writer.write_type(TYPE_THREADGROUP); |
88 const intptr_t start = writer.current_offset(); |
113 thread_group_set.serialize(writer); |
89 // invoke the serializer routine |
114 } |
90 _serializer->serialize(writer); |
115 |
91 if (start == writer.current_offset() ) { |
116 void JfrTypeManager::write_threads(JfrCheckpointWriter& writer) { |
92 // the serializer implementation did nothing, rewind to restore |
117 serialize_threads(writer); |
93 writer.set_context(ctx); |
118 serialize_thread_groups(writer); |
94 return; |
119 } |
95 } |
120 |
96 if (_permit_cache) { |
121 void JfrTypeManager::create_thread_blob(Thread* t) { |
97 _cache = writer.copy(&ctx); |
122 assert(t != NULL, "invariant"); |
98 } |
123 ResourceMark rm(t); |
|
124 HandleMark hm(t); |
|
125 JfrThreadConstant type_thread(t); |
|
126 JfrCheckpointWriter writer(t, true, THREADS); |
|
127 writer.write_type(TYPE_THREAD); |
|
128 type_thread.serialize(writer); |
|
129 // create and install a checkpoint blob |
|
130 t->jfr_thread_local()->set_thread_blob(writer.move()); |
|
131 assert(t->jfr_thread_local()->has_thread_blob(), "invariant"); |
|
132 } |
|
133 |
|
134 void JfrTypeManager::write_thread_checkpoint(Thread* t) { |
|
135 assert(t != NULL, "invariant"); |
|
136 ResourceMark rm(t); |
|
137 HandleMark hm(t); |
|
138 JfrThreadConstant type_thread(t); |
|
139 JfrCheckpointWriter writer(t, true, THREADS); |
|
140 writer.write_type(TYPE_THREAD); |
|
141 type_thread.serialize(writer); |
99 } |
142 } |
100 |
143 |
101 class SerializerRegistrationGuard : public StackObj { |
144 class SerializerRegistrationGuard : public StackObj { |
102 private: |
145 private: |
103 static Semaphore _mutex_semaphore; |
146 static Semaphore _mutex_semaphore; |
113 Semaphore SerializerRegistrationGuard::_mutex_semaphore(1); |
156 Semaphore SerializerRegistrationGuard::_mutex_semaphore(1); |
114 |
157 |
115 typedef JfrDoublyLinkedList<JfrSerializerRegistration> List; |
158 typedef JfrDoublyLinkedList<JfrSerializerRegistration> List; |
116 typedef StopOnNullIterator<const List> Iterator; |
159 typedef StopOnNullIterator<const List> Iterator; |
117 static List types; |
160 static List types; |
118 static List safepoint_types; |
|
119 |
161 |
120 void JfrTypeManager::destroy() { |
162 void JfrTypeManager::destroy() { |
121 SerializerRegistrationGuard guard; |
163 SerializerRegistrationGuard guard; |
122 Iterator iter(types); |
164 Iterator iter(types); |
123 JfrSerializerRegistration* registration; |
165 JfrSerializerRegistration* registration; |
124 while (iter.has_next()) { |
166 while (iter.has_next()) { |
125 registration = types.remove(iter.next()); |
167 registration = types.remove(iter.next()); |
126 assert(registration != NULL, "invariant"); |
168 assert(registration != NULL, "invariant"); |
127 delete registration; |
169 delete registration; |
128 } |
170 } |
129 Iterator sp_type_iter(safepoint_types); |
171 } |
130 while (sp_type_iter.has_next()) { |
172 |
131 registration = safepoint_types.remove(sp_type_iter.next()); |
173 void JfrTypeManager::on_rotation() { |
132 assert(registration != NULL, "invariant"); |
|
133 delete registration; |
|
134 } |
|
135 } |
|
136 |
|
137 void JfrTypeManager::write_types(JfrCheckpointWriter& writer) { |
|
138 const Iterator iter(types); |
174 const Iterator iter(types); |
139 while (iter.has_next()) { |
175 while (iter.has_next()) { |
140 iter.next()->invoke(writer); |
176 iter.next()->on_rotation(); |
141 } |
177 } |
142 } |
|
143 |
|
144 void JfrTypeManager::write_safepoint_types(JfrCheckpointWriter& writer) { |
|
145 assert(SafepointSynchronize::is_at_safepoint(), "invariant"); |
|
146 const Iterator iter(safepoint_types); |
|
147 while (iter.has_next()) { |
|
148 iter.next()->invoke(writer); |
|
149 } |
|
150 } |
|
151 |
|
152 void JfrTypeManager::create_thread_blob(JavaThread* jt) { |
|
153 assert(jt != NULL, "invariant"); |
|
154 ResourceMark rm(jt); |
|
155 HandleMark hm(jt); |
|
156 JfrThreadConstant type_thread(jt); |
|
157 JfrCheckpointWriter writer(false, true, jt); |
|
158 writer.write_type(TYPE_THREAD); |
|
159 type_thread.serialize(writer); |
|
160 // create and install a checkpoint blob |
|
161 jt->jfr_thread_local()->set_thread_blob(writer.move()); |
|
162 assert(jt->jfr_thread_local()->has_thread_blob(), "invariant"); |
|
163 } |
|
164 |
|
165 void JfrTypeManager::write_thread_checkpoint(JavaThread* jt) { |
|
166 assert(jt != NULL, "JavaThread is NULL!"); |
|
167 ResourceMark rm(jt); |
|
168 HandleMark hm(jt); |
|
169 JfrThreadConstant type_thread(jt); |
|
170 JfrCheckpointWriter writer(false, true, jt); |
|
171 writer.write_type(TYPE_THREAD); |
|
172 type_thread.serialize(writer); |
|
173 } |
178 } |
174 |
179 |
175 #ifdef ASSERT |
180 #ifdef ASSERT |
176 static void assert_not_registered_twice(JfrTypeId id, List& list) { |
181 static void assert_not_registered_twice(JfrTypeId id, List& list) { |
177 const Iterator iter(list); |
182 const Iterator iter(list); |
179 assert(iter.next()->id() != id, "invariant"); |
184 assert(iter.next()->id() != id, "invariant"); |
180 } |
185 } |
181 } |
186 } |
182 #endif |
187 #endif |
183 |
188 |
184 static bool register_type(JfrTypeId id, bool require_safepoint, bool permit_cache, JfrSerializer* serializer) { |
189 static bool new_registration = false; |
|
190 |
|
191 static bool register_static_type(JfrTypeId id, bool permit_cache, JfrSerializer* serializer) { |
185 assert(serializer != NULL, "invariant"); |
192 assert(serializer != NULL, "invariant"); |
186 JfrSerializerRegistration* const registration = new JfrSerializerRegistration(id, permit_cache, serializer); |
193 JfrSerializerRegistration* const registration = new JfrSerializerRegistration(id, permit_cache, serializer); |
187 if (registration == NULL) { |
194 if (registration == NULL) { |
188 delete serializer; |
195 delete serializer; |
189 return false; |
196 return false; |
190 } |
197 } |
191 if (require_safepoint) { |
198 assert(!types.in_list(registration), "invariant"); |
192 assert(!safepoint_types.in_list(registration), "invariant"); |
199 DEBUG_ONLY(assert_not_registered_twice(id, types);) |
193 DEBUG_ONLY(assert_not_registered_twice(id, safepoint_types);) |
200 if (JfrRecorder::is_recording()) { |
194 safepoint_types.prepend(registration); |
201 JfrCheckpointWriter writer(STATICS); |
195 } else { |
202 registration->invoke(writer); |
196 assert(!types.in_list(registration), "invariant"); |
203 new_registration = true; |
197 DEBUG_ONLY(assert_not_registered_twice(id, types);) |
204 } |
198 types.prepend(registration); |
205 types.prepend(registration); |
199 } |
|
200 return true; |
206 return true; |
201 } |
207 } |
202 |
208 |
203 bool JfrTypeManager::initialize() { |
209 bool JfrTypeManager::initialize() { |
204 SerializerRegistrationGuard guard; |
210 SerializerRegistrationGuard guard; |
205 |
211 register_static_type(TYPE_FLAGVALUEORIGIN, true, new FlagValueOriginConstant()); |
206 // register non-safepointing type serialization |
212 register_static_type(TYPE_INFLATECAUSE, true, new MonitorInflateCauseConstant()); |
207 register_type(TYPE_FLAGVALUEORIGIN, false, true, new FlagValueOriginConstant()); |
213 register_static_type(TYPE_GCCAUSE, true, new GCCauseConstant()); |
208 register_type(TYPE_INFLATECAUSE, false, true, new MonitorInflateCauseConstant()); |
214 register_static_type(TYPE_GCNAME, true, new GCNameConstant()); |
209 register_type(TYPE_GCCAUSE, false, true, new GCCauseConstant()); |
215 register_static_type(TYPE_GCWHEN, true, new GCWhenConstant()); |
210 register_type(TYPE_GCNAME, false, true, new GCNameConstant()); |
216 register_static_type(TYPE_GCTHRESHOLDUPDATER, true, new GCThresholdUpdaterConstant()); |
211 register_type(TYPE_GCWHEN, false, true, new GCWhenConstant()); |
217 register_static_type(TYPE_METADATATYPE, true, new MetadataTypeConstant()); |
212 register_type(TYPE_GCTHRESHOLDUPDATER, false, true, new GCThresholdUpdaterConstant()); |
218 register_static_type(TYPE_METASPACEOBJECTTYPE, true, new MetaspaceObjectTypeConstant()); |
213 register_type(TYPE_METADATATYPE, false, true, new MetadataTypeConstant()); |
219 register_static_type(TYPE_REFERENCETYPE, true, new ReferenceTypeConstant()); |
214 register_type(TYPE_METASPACEOBJECTTYPE, false, true, new MetaspaceObjectTypeConstant()); |
220 register_static_type(TYPE_NARROWOOPMODE, true, new NarrowOopModeConstant()); |
215 register_type(TYPE_REFERENCETYPE, false, true, new ReferenceTypeConstant()); |
221 register_static_type(TYPE_COMPILERPHASETYPE, true, new CompilerPhaseTypeConstant()); |
216 register_type(TYPE_NARROWOOPMODE, false, true, new NarrowOopModeConstant()); |
222 register_static_type(TYPE_CODEBLOBTYPE, true, new CodeBlobTypeConstant()); |
217 register_type(TYPE_COMPILERPHASETYPE, false, true, new CompilerPhaseTypeConstant()); |
223 register_static_type(TYPE_VMOPERATIONTYPE, true, new VMOperationTypeConstant()); |
218 register_type(TYPE_CODEBLOBTYPE, false, true, new CodeBlobTypeConstant()); |
224 register_static_type(TYPE_THREADSTATE, true, new ThreadStateConstant()); |
219 register_type(TYPE_VMOPERATIONTYPE, false, true, new VMOperationTypeConstant()); |
|
220 register_type(TYPE_THREADSTATE, false, true, new ThreadStateConstant()); |
|
221 |
|
222 // register safepointing type serialization |
|
223 register_type(TYPE_THREADGROUP, true, false, new JfrThreadGroupConstant()); |
|
224 register_type(TYPE_THREAD, true, false, new JfrThreadConstantSet()); |
|
225 return true; |
225 return true; |
226 } |
226 } |
227 |
227 |
228 // implementation for the static registration function exposed in the JfrSerializer api |
228 // implementation for the static registration function exposed in the JfrSerializer api |
229 bool JfrSerializer::register_serializer(JfrTypeId id, bool require_safepoint, bool permit_cache, JfrSerializer* serializer) { |
229 bool JfrSerializer::register_serializer(JfrTypeId id, bool permit_cache, JfrSerializer* serializer) { |
230 SerializerRegistrationGuard guard; |
230 SerializerRegistrationGuard guard; |
231 return register_type(id, require_safepoint, permit_cache, serializer); |
231 return register_static_type(id, permit_cache, serializer); |
232 } |
232 } |
|
233 |
|
234 bool JfrTypeManager::has_new_static_type() { |
|
235 if (new_registration) { |
|
236 SerializerRegistrationGuard guard; |
|
237 new_registration = false; |
|
238 return true; |
|
239 } |
|
240 return false; |
|
241 } |
|
242 |
|
243 void JfrTypeManager::write_static_types(JfrCheckpointWriter& writer) { |
|
244 SerializerRegistrationGuard guard; |
|
245 const Iterator iter(types); |
|
246 while (iter.has_next()) { |
|
247 iter.next()->invoke(writer); |
|
248 } |
|
249 new_registration = false; |
|
250 } |